How to better smooth the fading edges of an arc

I am creating a frame plugin. The arc seems to be drawn okay as shown here:
enter image description here

But if you look carefully, you will notice the wild edges compared to this idle frame:
enter image description here

So, how can I smooth the edges to match the second image, given this code piece:

function drawFancyArcFrame(mainCtx, opts) {
        const {
          cx, cy, radius, width, startDeg, sweepDeg,
          color1, color2, capStyle = 'feather',
          capLengthPx = 24, pixelSize = 4
        } = opts;

        if (sweepDeg <= 0 || width <= 0) return;

        const startRad = (startDeg * Math.PI) / 180;
        const endRad   = ((startDeg + sweepDeg) * Math.PI) / 180;

        const W = mainCtx.canvas.width;
        const H = mainCtx.canvas.height;

        const off = document.createElement('canvas');
        off.width = W; off.height = H;
        const ctx = off.getContext('2d');

        const grad = ctx.createLinearGradient(0, 0, W, H);
        grad.addColorStop(0, color1);
        grad.addColorStop(1, color2);

        // draw base arc with flat ends so we can sculpt
        ctx.save();
        ctx.strokeStyle = grad;
        ctx.lineWidth = width;
        ctx.lineCap = 'butt';
        ctx.globalAlpha = 0.85;
        ctx.beginPath();
        ctx.arc(cx, cy, radius, startRad, endRad, false);
        ctx.stroke();
        ctx.restore();

        // endpoints + tangents
        const sx = cx + radius * Math.cos(startRad);
        const sy = cy + radius * Math.sin(startRad);
        const ex = cx + radius * Math.cos(endRad);
        const ey = cy + radius * Math.sin(endRad);
        const tStart = startRad + Math.PI / 2;
        const tEnd   = endRad   + Math.PI / 2;

        // erasers (destination-out)
        const eraseFeather = (x, y, ang) => {
          ctx.save();
          ctx.translate(x, y);
          ctx.rotate(ang);
          ctx.globalCompositeOperation = 'destination-out';
          const g = ctx.createLinearGradient(0, 0, capLengthPx, 0);
          g.addColorStop(0, 'rgba(0,0,0,1)');
          g.addColorStop(1, 'rgba(0,0,0,0)');
          ctx.fillStyle = g;
          ctx.fillRect(0, -width/2, capLengthPx, width);
          ctx.restore();
        };

        const eraseChop = (x, y, ang) => {
          ctx.save();
          ctx.translate(x, y);
          ctx.rotate(ang);
          ctx.globalCompositeOperation = 'destination-out';
          ctx.beginPath();
          ctx.moveTo(0, -width/2);
          ctx.lineTo(capLengthPx, 0);
          ctx.lineTo(0, width/2);
          ctx.closePath();
          ctx.fillStyle = 'rgba(0,0,0,1)';
          ctx.fill();
          ctx.restore();
        };

        const erasePixel = (x, y, ang) => {
          ctx.save();
          ctx.translate(x, y);
          ctx.rotate(ang);
          ctx.globalCompositeOperation = 'destination-out';
          const cols = Math.ceil(capLengthPx / pixelSize);
          const rows = Math.ceil(width / pixelSize);
          const y0 = -width / 2;
          for (let c = 0; c < cols; c++) {
            const frac = 1 - (c / cols);
            const activeRows = Math.max(1, Math.floor(rows * frac));
            const x0 = c * pixelSize;
            for (let r = 0; r < activeRows; r++) {
              if (Math.random() < 0.85) {
                const yCell = y0 + r * pixelSize;
                ctx.fillStyle = 'rgba(0,0,0,1)';
                ctx.fillRect(x0, yCell, pixelSize, pixelSize);
              }
            }
          }
          ctx.restore();
        };

        switch (capStyle) {
          case 'feather':
            eraseFeather(sx, sy, tStart);
            eraseFeather(ex, ey, tEnd + Math.PI);
            break;
          case 'chop':
            eraseChop(sx, sy, tStart);
            eraseChop(ex, ey, tEnd + Math.PI);
            break;
          case 'pixel':
            erasePixel(sx, sy, tStart);
            erasePixel(ex, ey, tEnd + Math.PI);
            break;
        }

        mainCtx.drawImage(off, 0, 0);
      }

I want to remove the straight-edge seams to match the second image’s smooth fading.
enter image description here

How to better smooth out the edges of this drawn arc

I am creating this frame plugin. The arc seems to be drawn okay as shown here:
enter image description here

But if you look carefully, you will notice the wild edges compared to this idle frame:
enter image description here

So, how can I smooth the edges to match the second image, given this code piece:

function drawFancyArcFrame(mainCtx, opts) {
        const {
          cx, cy, radius, width, startDeg, sweepDeg,
          color1, color2, capStyle = 'feather',
          capLengthPx = 24, pixelSize = 4
        } = opts;

        if (sweepDeg <= 0 || width <= 0) return;

        const startRad = (startDeg * Math.PI) / 180;
        const endRad   = ((startDeg + sweepDeg) * Math.PI) / 180;

        const W = mainCtx.canvas.width;
        const H = mainCtx.canvas.height;

        const off = document.createElement('canvas');
        off.width = W; off.height = H;
        const ctx = off.getContext('2d');

        const grad = ctx.createLinearGradient(0, 0, W, H);
        grad.addColorStop(0, color1);
        grad.addColorStop(1, color2);

        // draw base arc with flat ends so we can sculpt
        ctx.save();
        ctx.strokeStyle = grad;
        ctx.lineWidth = width;
        ctx.lineCap = 'butt';
        ctx.globalAlpha = 0.85;
        ctx.beginPath();
        ctx.arc(cx, cy, radius, startRad, endRad, false);
        ctx.stroke();
        ctx.restore();

        // endpoints + tangents
        const sx = cx + radius * Math.cos(startRad);
        const sy = cy + radius * Math.sin(startRad);
        const ex = cx + radius * Math.cos(endRad);
        const ey = cy + radius * Math.sin(endRad);
        const tStart = startRad + Math.PI / 2;
        const tEnd   = endRad   + Math.PI / 2;

        // erasers (destination-out)
        const eraseFeather = (x, y, ang) => {
          ctx.save();
          ctx.translate(x, y);
          ctx.rotate(ang);
          ctx.globalCompositeOperation = 'destination-out';
          const g = ctx.createLinearGradient(0, 0, capLengthPx, 0);
          g.addColorStop(0, 'rgba(0,0,0,1)');
          g.addColorStop(1, 'rgba(0,0,0,0)');
          ctx.fillStyle = g;
          ctx.fillRect(0, -width/2, capLengthPx, width);
          ctx.restore();
        };

        const eraseChop = (x, y, ang) => {
          ctx.save();
          ctx.translate(x, y);
          ctx.rotate(ang);
          ctx.globalCompositeOperation = 'destination-out';
          ctx.beginPath();
          ctx.moveTo(0, -width/2);
          ctx.lineTo(capLengthPx, 0);
          ctx.lineTo(0, width/2);
          ctx.closePath();
          ctx.fillStyle = 'rgba(0,0,0,1)';
          ctx.fill();
          ctx.restore();
        };

        const erasePixel = (x, y, ang) => {
          ctx.save();
          ctx.translate(x, y);
          ctx.rotate(ang);
          ctx.globalCompositeOperation = 'destination-out';
          const cols = Math.ceil(capLengthPx / pixelSize);
          const rows = Math.ceil(width / pixelSize);
          const y0 = -width / 2;
          for (let c = 0; c < cols; c++) {
            const frac = 1 - (c / cols);
            const activeRows = Math.max(1, Math.floor(rows * frac));
            const x0 = c * pixelSize;
            for (let r = 0; r < activeRows; r++) {
              if (Math.random() < 0.85) {
                const yCell = y0 + r * pixelSize;
                ctx.fillStyle = 'rgba(0,0,0,1)';
                ctx.fillRect(x0, yCell, pixelSize, pixelSize);
              }
            }
          }
          ctx.restore();
        };

        switch (capStyle) {
          case 'feather':
            eraseFeather(sx, sy, tStart);
            eraseFeather(ex, ey, tEnd + Math.PI);
            break;
          case 'chop':
            eraseChop(sx, sy, tStart);
            eraseChop(ex, ey, tEnd + Math.PI);
            break;
          case 'pixel':
            erasePixel(sx, sy, tStart);
            erasePixel(ex, ey, tEnd + Math.PI);
            break;
        }

        mainCtx.drawImage(off, 0, 0);
      }

I want to remove the straight-edge seams to match the second image’s smooth fading.
enter image description here

React safe way to render children [duplicate]

I have multiple banner components that each render a <BannerAlert /> based on API data.
Each banner handles its own visibility logic — if the API response is false, it returns null; if true, it renders the banner.

Example of one banner:

import { Alert } from "@/ui";
import { useHook } from "@/utils";

export const OneChild = () => {
  const { data, isLoading } = useHook();
  if (isLoading || !data?.balances?.hasOneChild) return null;

  return (
    <Alert
      type="error"
      title="OneChild"
      message="OneChild is active."
    />
  );
};

On the dashboard, I want to display only the first banner that is not null (in order of priority).
I created a wrapper called RenderChildren that wraps all banners:

<RenderChildren>
  <OneChild />
  <SecondChild />
  <ThirdChild />
  <FourthChild />
</RenderChildren>

And here’s my first attempt:

export const RenderChildren = ({ children }: { children: React.ReactNode }) => {
  const childrenArray = React.Children.toArray(children);

  const validChildren = childrenArray.filter((child) => {
    if (!React.isValidElement(child)) return false;
    if (typeof child.type === 'function') {
      try {
        const rendered = (child.type as (props: unknown) => React.ReactNode)(child.props);
        return rendered !== null && rendered !== undefined;
      } catch {
        return false;
      }
    }
    return true;
  });

  const firstChild = validChildren[0];
  return firstChild || null;
};

This works, but it calls each component function manually (child.type(child.props)), which breaks React’s rules of hooks and is not safe.

What I’ve tried / What I know:

I understand that manually calling a component breaks React’s render cycle.

I’ve looked into React.Children.map() and cloneElement, but those don’t help detect what each child returns.

My supervisor asked me to find a more performant and React-safe approach — possibly similar to patterns used by packages like react-if or react-conditionally.

What’s a React-safe and performant pattern to render only the first non-null child among several conditional components?
Is there an established pattern or compositional approach (without manually invoking children) that achieves this?

JavaScript calculator returns wrong total (100 + 200, press enter, result is 300, press enter again, 100 + 100,press enter, result is 500) [closed]

I’m building a simple JavaScript calculator that supports keyboard and button inputs.

The Problem:

When I perform the following steps:

Type 100 + 200, then press Enter → result is 300, press Enter again(supposedly user accidentally press enter twice).

Then type 100 + 100, then press Enter → result becomes 500 (should be 200)

Each new input after pressing Enter should start a fresh calculation

How can I fix my logic so that each new calculation starts fresh after pressing Enter?

document.querySelector("#eight");
const nine = document.querySelector("#nine");
const point = document.querySelector("#point");
let operator = "";
let numbers = [undefined, undefined];
let isTotal = false;
let isFresh = false;
document.addEventListener("keydown", (event) => {
  let key = event.key;
  if (key === ".") {
    putPoint();
  }
  if (key === "0") {
    putZero();
  }
  if (key === "1") {
    putOne();
  }
  if (key === "2") {
    putTwo();
  }
  if (key === "3") {
    putThree();
  }
  if (key === "4") {
    putFour();
  }
  if (key === "5") {
    putFive();
  }
  if (key === "6") {
    putSix();
  }
  if (key === "7") {
    putSeven();
  }
  if (key === "8") {
    putEight();
  }
  if (key === "9") {
    putNine();
  }
  if (key === "Escape") {
    clearDisplay();
  }
  if (key === "+") {
    addNumber();
  }
  if (key === "-") {
    subtractNumbers();
  }
  if (key === "*") {
    multiplyNumbers();
  }
  if (key === "/") {
    divideNumbers();
  }
  if (key === "Enter") {
    event.preventDefault();
    totalNumbers();
  }
  if (key === "%") {
    percentage();
  }
});
point.addEventListener("click", putPoint);
function putPoint() {
  if (!calcDisplay.value.includes(".")) {
    calcDisplay.value += ".";
  }
}
function putZero() {
  if (
    calcDisplay.value === "+" ||
    calcDisplay.value === "-" ||
    calcDisplay.value === "/" ||
    calcDisplay.value === "*" ||
    isTotal ||
    isFresh
  ) {
    calcDisplay.value = "";
    if (isTotal) {
      numbers[0] = undefined;
    }
    isTotal = false;
    isFresh = false;
  }
  calcDisplay.value += "0";
}
zero.addEventListener("click", putZero);
one.addEventListener("click", putOne);
function putOne() {
  if (
    calcDisplay.value === "+" ||
    calcDisplay.value === "-" ||
    calcDisplay.value === "/" ||
    calcDisplay.value === "*" ||
    operator === "equals" ||
    isTotal ||
    isFresh
  ) {
    calcDisplay.value = "";
    if (isTotal) {
      numbers[0] = undefined;
    }
    isTotal = false;
    isFresh = false;
  }
  calcDisplay.value += "1";
}
two.addEventListener("click", putTwo);
function putTwo() {
  if (
    calcDisplay.value === "+" ||
    calcDisplay.value === "-" ||
    calcDisplay.value === "/" ||
    calcDisplay.value === "*" ||
    operator === "equals" ||
    isTotal ||
    isFresh
  ) {
    calcDisplay.value = "";
    if (isTotal) {
      numbers[0] = undefined;
    }
    isTotal = false;
    isFresh = false;
  }
  calcDisplay.value += "2";
}
three.addEventListener("click", putThree);
function putThree() {
  if (
    calcDisplay.value === "+" ||
    calcDisplay.value === "-" ||
    calcDisplay.value === "/" ||
    calcDisplay.value === "*" ||
    operator === "equals" ||
    isTotal ||
    isFresh
  ) {
    calcDisplay.value = "";
    if (isTotal) {
      numbers[0] = undefined;
    }
    isTotal = false;
    isFresh = false;
  }
  calcDisplay.value += "3";
}
four.addEventListener("click", putFour);
function putFour() {
  if (
    calcDisplay.value === "+" ||
    calcDisplay.value === "-" ||
    calcDisplay.value === "/" ||
    calcDisplay.value === "*" ||
    operator === "equals" ||
    isTotal ||
    isFresh
  ) {
    calcDisplay.value = "";
    if (isTotal) {
      numbers[0] = undefined;
    }
    isTotal = false;
    isFresh = false;
  }
  calcDisplay.value += "4";
}
five.addEventListener("click", putFive);
function putFive() {
  if (
    calcDisplay.value === "+" ||
    calcDisplay.value === "-" ||
    calcDisplay.value === "/" ||
    calcDisplay.value === "*" ||
    operator === "equals" ||
    isTotal ||
    isFresh
  ) {
    calcDisplay.value = "";
    if (isTotal) {
      numbers[0] = undefined;
    }
    isTotal = false;
    isFresh = false;
  }
  calcDisplay.value += "5";
}
six.addEventListener("click", putSix);
function putSix() {
  if (
    calcDisplay.value === "+" ||
    calcDisplay.value === "-" ||
    calcDisplay.value === "/" ||
    calcDisplay.value === "*" ||
    operator === "equals" ||
    isTotal ||
    isFresh
  ) {
    calcDisplay.value = "";
    if (isTotal) {
      numbers[0] = undefined;
    }
    isTotal = false;
    isFresh = false;
  }
  calcDisplay.value += "6";
}
seven.addEventListener("click", putSeven);
function putSeven() {
  if (
    calcDisplay.value === "+" ||
    calcDisplay.value === "-" ||
    calcDisplay.value === "/" ||
    calcDisplay.value === "*" ||
    operator === "equals" ||
    isTotal ||
    isFresh
  ) {
    calcDisplay.value = "";
    if (isTotal) {
      numbers[0] = undefined;
    }
    isTotal = false;
    isFresh = false;
  }
  calcDisplay.value += "7";
}
eight.addEventListener("click", putEight);
function putEight() {
  if (
    calcDisplay.value === "+" ||
    calcDisplay.value === "-" ||
    calcDisplay.value === "/" ||
    calcDisplay.value === "*" ||
    operator === "equals" ||
    isTotal ||
    isFresh
  ) {
    calcDisplay.value = "";
    if (isTotal) {
      numbers[0] = undefined;
    }
    isTotal = false;
    isFresh = false;
  }
  calcDisplay.value += "8";
}
nine.addEventListener("click", putNine);
function putNine() {
  if (
    calcDisplay.value === "+" ||
    calcDisplay.value === "-" ||
    calcDisplay.value === "/" ||
    calcDisplay.value === "*" ||
    operator === "equals" ||
    isTotal ||
    isFresh
  ) {
    calcDisplay.value = "";
    if (isTotal) {
      numbers[0] = undefined;
    }
    isTotal = false;
    isFresh = false;
  }
  calcDisplay.value += "9";
}
clearBtn.addEventListener("click", clearDisplay);
function clearDisplay() {
  calcDisplay.value = "";
  numbers[0] = undefined;
  numbers[1] = undefined;
  operator = undefined;
}
plus.addEventListener("click", addNumber);
function addNumber() {
  if (operator === "division") {
    let quo = numbers[0] / Number(calcDisplay.value);
    numbers[0] = quo;
    calcDisplay.value = "+";
  } else if (operator === "subtraction") {
    let diff = numbers[0] - Number(calcDisplay.value);
    numbers[0] = diff;
    calcDisplay.value = "+";
  } else if (operator === "multiplication") {
    let prod = numbers[0] * Number(calcDisplay.value);
    numbers[0] = prod;
    calcDisplay.value = "*";
  } else {
    numbers[1] = Number(calcDisplay.value);
    if (numbers[0] === undefined) {
      numbers[0] = numbers[1];
    } else {
      numbers[0] = numbers[0] + numbers[1];
    }
    numbers[1] = 0;
    calcDisplay.value = "+";
  }
  operator = "addition";
}
minus.addEventListener("click", subtractNumbers);
function subtractNumbers() {
  if (operator === "addition") {
    let sum = numbers[0] + Number(calcDisplay.value);
    numbers[0] = sum;
    calcDisplay.value = "-";
  } else if (operator === "division") {
    let quo = numbers[0] / Number(calcDisplay.value);
    numbers[0] = quo;
    calcDisplay.value = "-";
  } else if (operator === "multiplication") {
    let prod = numbers[0] * Number(calcDisplay.value);
    numbers[0] = prod;
    calcDisplay.value = "-";
  } else {
    numbers[1] = Number(calcDisplay.value);
    if (numbers[0] === undefined) {
      numbers[0] = numbers[1];
    } else {
      numbers[0] = numbers[0] - numbers[1];
    }
    numbers[1] = 0;
    calcDisplay.value = "-";
  }
  operator = "subtraction";
}
multiply.addEventListener("click", multiplyNumbers);
function multiplyNumbers() {
  if (operator === "addition") {
    let sum = numbers[0] + Number(calcDisplay.value);
    numbers[0] = sum;
    calcDisplay.value = "*";
  } else if (operator === "subtraction") {
    let diff = numbers[0] - Number(calcDisplay.value);
    numbers[0] = diff;
    calcDisplay.value = "*";
  } else if (operator === "division") {
    let quo = numbers[0] / Number(calcDisplay.value);
    numbers[0] = quo;
    calcDisplay.value = "*";
  } else {
    numbers[1] = Number(calcDisplay.value);
    if (numbers[0] === undefined) {
      numbers[0] = numbers[1];
    } else {
      numbers[0] = numbers[0] * numbers[1];
    }
    numbers[1] = 0;
    calcDisplay.value = "*";
  }
  operator = "multiplication";
}
divide.addEventListener("click", divideNumbers);
function divideNumbers() {
  if (operator === "addition") {
    let sum = numbers[0] + Number(calcDisplay.value);
    numbers[0] = sum;
    calcDisplay.value = "/";
  } else if (operator === "subtraction") {
    let diff = numbers[0] - Number(calcDisplay.value);
    numbers[0] = diff;
    calcDisplay.value = "/";
  } else if (operator === "multiplication") {
    let prod = numbers[0] * Number(calcDisplay.value);
    numbers[0] = prod;
    calcDisplay.value = "/";
  } else {
    numbers[1] = Number(calcDisplay.value);
    if (numbers[0] === undefined) {
      numbers[0] = numbers[1];
    } else {
      numbers[0] = numbers[0] / numbers[1];
    }
    numbers[1] = 0;
    calcDisplay.value = "/";
  }
  operator = "division";
}
equal.addEventListener("click", totalNumbers);

function totalNumbers() {
  numbers[1] = Number(calcDisplay.value); // second input
  let result;

  if (operator === "addition") {
    result = numbers[0] + numbers[1];
  } else if (operator === "subtraction") {
    result = numbers[0] - numbers[1];
  } else if (operator === "multiplication") {
    result = numbers[0] * numbers[1];
  } else if (operator === "division") {
    result = numbers[0] / numbers[1];
  } else {
    // no operator → just return current value
    result = numbers[1];
    isTotal = false;
    calcDisplay.value = result;
    numbers[1] = undefined;
    isFresh = true;
    return;
  }

  calcDisplay.value = result;

  // keep result as first number, reset second + operator
  numbers[0] = result;
  numbers[1] = undefined;
  operator = "";
  isTotal = true;
}

plusMinus.addEventListener("click", negateNumber);
function negateNumber() {
  let result = Number(calcDisplay.value) * -1;
  calcDisplay.value = result;
}
percent.addEventListener("click", percentage);
function percentage() {
  if (numbers[0] === undefined || numbers[0] === 0) {
    calcDisplay.value = 0;
  } else {
    let point = calcDisplay.value / 100;
    calcDisplay.value = numbers[0] * point;
  }
}

I know there could be more potential issues as I am not done yet debugging my code but lets focus first on the issue I stated above. If you need more information just ask and I will give it you. Thank you!

axios vue might be first returning blank – vue3-easy-table not working

I am new to VUE and react. I have created an app with direct grids but want to use an API.
What is happening is both the implementations i have are giving development tools errors and although the data on the table i have done from scratch from my api trying to use a plugin the data isn’t coming through.

enter image description here

enter image description here

code with user and password removed. Again the problem specifically is the Table2

App.vue

<template>
  <Layout>
      <div>
      <HelloWorld> </HelloWorld>
      <Table2 :items="content"> </Table2>
      <DataTable :items="content"> </DataTable>
     
  </div>
  </Layout>
</template>


<script setup>

import axios from 'axios'
import { ref, onMounted } from 'vue'
import Layout from "./components/Layout.vue"
import HelloWorld from "./components/HelloWorld.vue"
import DataTable from "./components/DataTable.vue"
import Table2 from "./components/Table2.vue"
const content = ref('')
const author = ref('')

onMounted(async () => {
  try {
    // Read credentials from Vite environment variables when available. These should be set as
    // VITE_API_USER and VITE_API_PASS in a .env file (not committed).
    const apiUser = import.meta.env.VITE_API_USER || 'APIUSER'
    const apiPass = import.meta.env.VITE_API_PASS || 'APIPASS'

    const response = await axios.get("http://srhttiedev.srht.nhs.uk/api/winpathmissingresultaudit/", {
      auth: {
        username: apiUser,
        password: apiPass
      }
    })
    content.value = await response.data
  } catch (e) {
    content.value = 'Failed to fetch quote.'
  }
})
</script>

The one i want to work


<script lang="ts" setup>


// Define props properly in script setup
const props = defineProps({
    items: {
        type: Array,
        required: true
    }
})


import EasyDataTable from 'vue3-easy-data-table';
// CSS for the table component
import 'vue3-easy-data-table/dist/style.css';
const headers: Header[] = [
  { text: "SpecimenID", value: "player" },
  { text: "HospitalNo", value: "team"},
  { text: "NHSNo", value: "number"},
  { text: "Patient Name", value: "position"},
  { text: "Source Code", value: "indicator.height"},
  { text: "Source Desc", value: "indicator.weight", sortable: true},
  { text: "Source Classification Code", value: "lastAttended", width: 200},
  { text: "Source Class Desc", value: "country"},
];
</script>

<template>

 <EasyDataTable
    :headers="headers"
    :items="items"
  />
</template>

The one that does work but i’d rather probably use a library because will give me more options

<script setup>

// Define props properly in script setup
const props = defineProps({
    items: {
        type: Array,
        required: true
    }
})
</script>

<template>



       <table class="table table-striped table-hover">
    <thead>
      <tr>
        <th>SpecimenID</th>
        <th>Hospital Number</th>
        <th>HospitalNo Type</th>
        <th>NHSNo</th>
        <th>Patient Name</th>
        <th>Source Code</th>
        <th> Source Desc</th>
        <th> Source Classification Code</th>
        <th>Source Class Desc</th>
        <th> Message Date</th>
        <th> Actioned?</th>
      </tr>
    </thead>
    <tbody>
      <tr v-for="(item, index) in props.items" :key="item.specID">
            <td>{{item.specID}}</td>
             <td>{{item.hospNo}}</td>
              <td>{{item.hospNoType}}</td>
               <td>{{item.patientName}}</td>
                <td>{{item.sourceCode}}</td>
                 <td>{{item.sourceDesc}}</td>
                  <td>{{item.sourceCCode}}</td>
                   <td>{{item.sourceCDesc}}</td>
                    <td>{{item.msgDate}}</td>
                     <td>{{item.actioned}}</td>
                     <td><a href="#"> Details</a></td>
        </tr>
    </tbody>
  </table>
  
    <table>
       
    </table>
</template>

want the table populated but it is not populating right and no warning about the blank string

Sorting items in a Pina store very slow

I have a Pinia store defined like this:

export type Era = {
  id: number
  name: string
  start_year: number
  end_year: number
  item_count: number
}

const settingStore = {
    eras: ref([] as Era[]),
    // ...
  }

In my component:

export default {
  data: () => ({
    settingStore: useSettingStore(),
  }),
  computed: {
    eraTree() {
      const sortFunc = (a, b) => a.start_year - b.start_year
      const erasRaw = this.settingStore.eras
      // or const erasRaw = JSON.parse(JSON.stringify(this.settingStore.eras))
      console.log('Starting sort')
      const s = performance.now()
      const eras = erasRaw.sort(sortFunc)
      console.log(`sorted ${erasRaw.length} eras in ${performance.now() - s}`)

With 2400 eras, this sort takes 17 seconds! Sorting a non-reactive copy takes less than 1 millisecond.

Why is it so slow? Is this expected? I don’t think there are even any watchers on eras, there are no computed properties or similar.

Is it possible to recreate the old TV effect using css

Is it possible to recreate the old TV effect from the photos using CSS and JS?
enter image description here
enter image description here
I found a page that does it perfectly, but I couldn’t extract only the vignette and scanlines part:

https://codepen.io/Mobius1/pen/ZNgwbr

css

.vignette {
    background-image: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/86186/crt.png);
    @include fill;
        background-repeat: no-repeat;
        background-size: 100% 100%; 
    z-index: 10000;
}
.scanlines {
    @include fill;
    z-index: 9999;
    background: linear-gradient(
            transparentize($screen-background, 1) 50%,
            transparentize(darken($screen-background, 10), 0.75) 50%
        ),
        linear-gradient(
            90deg,
            transparentize(#ff0000, 0.94),
            transparentize(#00ff00, 0.98),
            transparentize(#0000ff, 0.94)
        );
    background-size: 100% 2px, 3px 100%;
    pointer-events: none;
}

Injecting script tags using javascript

I have a CRM that the front end is 100% javascript/html. The framework injects all the content directly into the page using javascript/jquery. Most script tags work well this way, however some embed code (script tags) just won’t work — however, it will work when I inject it using google tag manager.

My suspicion is that some of these libraries must use document.currentScript and that property isn’t set correctly in these instances.

I cannot determine what Google Tag Manager is doing differently that makes these injected script tags work.

The code I’m using is:

$('head').append($variableContainingScriptTag);

again, this code works for most things, but sometimes the code included doesn’t run correctly.

I’m thinking that if I could “inject”/append this code in the same manner Google Tag Manager does (and I usually click the box to support document.write), It’d work properly.

d3 tooltip is part of the DOM, but not visible

I’m trying to add a tooltip to data points in a d3 line chart. I determined that I couldn’t append the tooltip to “svg” — it was never visible. I could append a tooltip to the body html tag, but then if I had multiple line charts on my page, the tooltip wasn’t attached to each particular graph. I’ve tried appending the tooltip to the listeningRect shape and the rect shape. I see the tooltip in the DOM, but it isn’t visible. Why isn’t it visible and how should the tooltip be attached?

var data = [ {'year':'2007', 'percent':'.05'}, {'year':'2008', 'percent':'.10'}, {'year':'2009', 'percent':'.15'}, {'year':'2010', 'percent':'.25'} ];

sendData(data);
function sendData(data) {
    const width = 1140;
    const height = 400;
    const marginTop = 20;
    const marginRight = 20;
    const marginBottom = 50;
    const marginLeft = 70;

    //var data = [ {'year':'2007', 'percent':'.05'}, {'year':'2008', 'percent':'.10'}, {'year':'2009', 'percent':'.15'} ]

    const x = d3.scaleUtc()
        .domain([new Date("2007-01-01"), new Date("2023-01-01")])
        .range([marginLeft, width - marginRight]); //same as .range([70,1120])

    const y = d3.scaleLinear()
        .domain([0, .5])
        .range([height - marginBottom, marginTop]); //same as .range([350, 20])

    const svg = d3.create("svg")
        .attr("width", width)
        .attr("height", height);

    svg.append("g")
        .attr("transform", `translate(0,${height - marginBottom})`)
        .call(d3.axisBottom(x)
            .ticks(d3.utcYear.every(1))
        );

    svg.append("text")
        .attr("class", "x label")
        .attr("text-anchor", "end")
        .attr("x", width/2)
        .attr("y", height - 6)
        .text("Year");

    svg.append("text")
        .attr("class", "y label")
        .attr("text-anchor", "end")
        .attr("x", -height/3)
        .attr("y", 6)
        .attr("dy", ".75em")
        .attr("transform", "rotate(-90)")
        .text("Percent");

    svg.append("g")
        .attr("transform", `translate(${marginLeft},0)`)
        .call(d3.axisLeft(y));

    var heightOfY = height-marginBottom;
    var Xmin = 2007;
    var Xmax = 2023;
    var numTicks = Xmax - Xmin + 1; //have to count the 0 point, so add 1
    var XmaxRange = width - marginRight;
    var eachTickWidth = XmaxRange / numTicks;

    let path=svg.append("path")
        .datum(data)
        .attr("fill", "none")
        .attr("stroke", "steelblue")
        .attr("stroke-width", 1.5)
        .attr("d", d3.line()
            .x(function(d) {
                //return x(d.year)
                var mine = ((d.year - Xmin)*eachTickWidth) + marginLeft;
                //return x(d.year);
                return(mine); console.log(d.year);
            })
            .y(function(d) {
                return y(d.percent)
            })
        );

    /*const tooltip = d3.select("svg") //doesn't appear
        .append("div")
        .attr("class", "tooltip");
    */

    const circle = svg.append("circle")
        .attr("r", 0)
        .attr("fill","steelblue")
        .style("stroke","white")
        .attr("opacity", .70)
        .style("pointer-events","none");

    const listeningRect = svg.append("rect")
        .datum(data)
        .attr("width", width)
        .attr("height", height);
        
    const tooltip = listeningRect //will appear if attached to d3.select("body"), but won't be linked to a particular chart if there are multiple charts
        .append("div")
        .attr("class", "tooltip");
        
    
    const dataToDate = d => new Date(d.year, 0, 1);

    listeningRect.on("mousemove", function(event){
        const [xCoord] = d3.pointer(event, this);
        const bisectData = d3.bisector(d => dataToDate(d)).left;
        const x0 = x.invert(xCoord);
        const i = bisectData(data, x0, 1);
        const d0 = data[i-1];
        const d1 = data[i];
        const d = d1 && (x0 - dataToDate(d0) > dataToDate(d1) - x0) ? d1 : d0;
        const xPos = x(dataToDate(d));
        const yPos = y(d.percent);
        
        
        circle.attr("cx", xPos)
            .attr("cy", yPos);
        
        circle.transition()
        .duration(50)
        .attr("r", 5);
        
        tooltip //is attached to listeningRect in the DOM
        .style("display","block")
        .style("left",`${xPos + 10}px`)
        .style("top", `${yPos + 10}px`)
        .html("<strong>Year:</strong> " + d.year + "<br/><strong>% with non-medial exemption: </strong> " + (d.percent*100) + "%");

        //console.log({xCoord, x0, d0, d1, d: dataToDate(d), xPos});
    });
    
    listeningRect.on("mouseout", function(event){
        tooltip
        .style("display","none");
    });
    container.append(svg.node());

} //end function sendData
.x.label, .y.label {
    font-weight: bold;
    font-size: 1rem;
}
.x.label {
    margin-left: -50%;
}

rect {
    pointer-events: all;
    fill-opacity: 0;
    stroke-opacity: 0;
    z-index: 1;
    background-color: transparent;
}

.tooltip {
    position: absolute;
    padding: 10px;
    background-color: steelblue;
    color: white;
    border: 1px solid white;
    border-radius: 10px;
    display: none;
    opacity: .8;
    z-index: 999;
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.9.0/d3.min.js"></script>
<div id="container"></div>

d3 tooltip isn’t appearing

I’ve been following a tutorial to put a tooltip and a circle on a data point as you move your mouse on a line chart: https://www.youtube.com/watch?v=uyPYxx-WGxc

However, when I try to get the tooltip to appear, nothing happens:
https://codepen.io/lschneiderman/pen/jEWygzX

What am I misunderstanding/doing wrong, please?

html:

<div id="container"></div>

css:

.x.label, .y.label {
    font-weight: bold;
    font-size: 1rem;
}
.x.label {
    margin-left: -50%;
}

rect {
    pointer-events: all;
    fill-opacity: 0;
    stroke-opacity: 0;
    z-index: 1;
    background-color: transparent;
}

.tooltip {
    position: absolute;
    padding: 10px;
    background-color: steelblue;
    color: white;
    border: 1px solid white;
    border-radius: 10px;
    display: none;
    opacity: .5;
}

js:

var data = [ {'year':'2007', 'percent':'.05'}, {'year':'2008', 'percent':'.10'}, {'year':'2009', 'percent':'.15'}, {'year':'2010', 'percent':'.25'} ];

sendData(data);
function sendData(data) {
    const width = 1140;
    const height = 400;
    const marginTop = 20;
    const marginRight = 20;
    const marginBottom = 50;
    const marginLeft = 70;

    //var data = [ {'year':'2007', 'percent':'.05'}, {'year':'2008', 'percent':'.10'}, {'year':'2009', 'percent':'.15'} ]

    const x = d3.scaleUtc()
        .domain([new Date("2007-01-01"), new Date("2023-01-01")])
        .range([marginLeft, width - marginRight]); //same as .range([70,1120])

    const y = d3.scaleLinear()
        .domain([0, .5])
        .range([height - marginBottom, marginTop]); //same as .range([350, 20])

    const svg = d3.create("svg")
        .attr("width", width)
        .attr("height", height);

    svg.append("g")
        .attr("transform", `translate(0,${height - marginBottom})`)
        .call(d3.axisBottom(x)
            .ticks(d3.utcYear.every(1))
        );

    svg.append("text")
        .attr("class", "x label")
        .attr("text-anchor", "end")
        .attr("x", width/2)
        .attr("y", height - 6)
        .text("Year");

    svg.append("text")
        .attr("class", "y label")
        .attr("text-anchor", "end")
        .attr("x", -height/3)
        .attr("y", 6)
        .attr("dy", ".75em")
        .attr("transform", "rotate(-90)")
        .text("Percent");

    svg.append("g")
        .attr("transform", `translate(${marginLeft},0)`)
        .call(d3.axisLeft(y));

    var heightOfY = height-marginBottom;
    var Xmin = 2007;
    var Xmax = 2023;
    var numTicks = Xmax - Xmin + 1; //have to count the 0 point, so add 1
    var XmaxRange = width - marginRight;
    var eachTickWidth = XmaxRange / numTicks;

    let path=svg.append("path")
        .datum(data)
        .attr("fill", "none")
        .attr("stroke", "steelblue")
        .attr("stroke-width", 1.5)
        .attr("d", d3.line()
            .x(function(d) {
                //return x(d.year)
                var mine = ((d.year - Xmin)*eachTickWidth) + marginLeft;
                //return x(d.year);
                return(mine); console.log(d.year);
            })
            .y(function(d) {
                return y(d.percent)
            })
        );

    const tooltip = d3.select("svg")
        .append("div")
        .attr("class", "tooltip");

    const circle = svg.append("circle")
        .attr("r", 0)
        .attr("fill","steelblue")
        .style("stroke","white")
        .attr("opacity", .70)
        .style("pointer-events","none");

    const listeningRect = svg.append("rect")
        .datum(data)
        .attr("width", width)
        .attr("height", height);

    const dataToDate = d => new Date(d.year, 0, 1);

    listeningRect.on("mousemove", function(event){
        const [xCoord] = d3.pointer(event, this);
        const bisectData = d3.bisector(d => dataToDate(d)).left;
        const x0 = x.invert(xCoord);
        const i = bisectData(data, x0, 1);
        const d0 = data[i-1];
        const d1 = data[i];
        const d = d1 && (x0 - dataToDate(d0) > dataToDate(d1) - x0) ? d1 : d0;
        const xPos = x(dataToDate(d));
        const yPos = y(d.percent);

        circle.attr("cx", xPos)
            .attr("cy", yPos);
        
        circle.transition()
        .duration(50)
        .attr("r", 5);
        
        tooltip
        .style("display","block")
        .style("left",`${xPos + 100}px`)
        .style("top", `${yPos + 50}px`)
        .html("<strong>Year:</strong>");

        //console.log({xCoord, x0, d0, d1, d: dataToDate(d), xPos});
    });

    container.append(svg.node());

} //end function sendData

Getting test ID issue while inspecting in Appium for IOS application (react native expo)

I’m working with a Tab Navigator that has four tabs — Topics, Category, Notification, and Account.

Some tabs have a screen directly attached to the tab, while others (like Category and Topics) contain nested Stack Navigators inside them.

The problem is that for the tabs with nested stack screens, I’m unable to inspect any elements inside those screens (for example, using test IDs or accessibility labels).

I’ve tried debugging but couldn’t find a way to make the elements inside these nested stack screens inspectable.

Has anyone faced this issue before or found a workaround to inspect elements within nested stack screens inside a Tab Navigator (especially on iOS)?

I also tried adding test IDs to each tab using the options prop, but it didn’t help.

Earlier, my root navigator was a Drawer Navigator, and in that setup, I was unable to inspect any of the tab screens — whether the screen was directly attached to the tab or nested inside a Stack Navigator.

However, when I removed the Drawer Navigator from the root, the issue changed — now, for the tabs that contain nested stack screens, I’m still unable to inspect any elements within those screens (for example, using test IDs or accessibility labels).

Data from a `MediaStream` can’t be recorded unless the `MediaStream` is atttached to a `HTMLMediaElement.srcObject`. Is this a Chromium bug? [closed]

On Chrome, data from a MediaStream isn’t decoded unless the MediaStream gets attached to a HTMLMediaElement.srcObject.

So when this MediaStream is passed to a MediaRecorder without performing the above, the MediaRecorder does not receive any data. But once the MediaStream is passed to a HTMLMediaElement.srcObject, both the HTMLMediaElement and the MediaRecorder receives data from the MediaStream.

This means that the only way to record media is by attaching the MediaStream to a HTMLMediaElement.srcObject before data can be received from the MediaStream by any observer.

This led me to a hack because I don’t want to play the media but just record it. I created a HTMLMediaElement, hid it and muted it.

Isn’t this completely unnecessary?

Am I missing anything or probably doing it wrong? This is a behaviour I noticed on Chrome so I don’t know if this behaviour is correct according to the Media Capture, Stream and Media Stream Recording API specification.

How to create grid like structure using html css a parallex grid having animations [closed]

I’m trying to create this kind of structure, as you can see in the below image but I don’t know what this design called? like I’m want to create this white grid structure and on scroll this grid acutally move for more clearity I’m adding website link

text
enter image description here

I want to know what this style named or how to achieve or create this style a guide or reference where I can read about it.

Using $location and $anchorScroll to scroll a table data (td) into view

In my Angular JS web application running on a TV browser, I have a horizontal menu. (You can see the menu and the problem I’m experiencing in the photos.) I use $location.hash and $anchorScroll to scroll this menu. However, if even a tiny pixel of the menu items in the table is visible on the far right or left, anchorScroll does not perform the scrolling. But when I move to the next invisible table data, the scrolling works fine.

The function I use for scrolling and HTML code as follows:

<td ng-if="guide.currentNavigationSectionIndex == 2" id="guide-item-cat-{{$index}}" ng-repeat="item in guide.guideCatChildList">
                                                    <table ng-class="defaultSelectMenu" cellpadding="0" cellspacing="0">

                                                        <tr>
                                                            <td class=" norm guideCatTitle" align="center">


                                                                <div ng-class="{true: 'guide-menu-tab-selected', false: 'guide-menu-tab'}[guide.selectedGuideId == item.ID]" ng-style="((guide.selectedGuideIndex == $index) && (guide.selectWelcomePage != 'welcome1')) &&
                                                                {'background':(vm.selectWelcomePage != 'welcome1' ? (guide.guideMenuNoneSelectTextColor) : 'white'), 
                                                                'color':(vm.selectWelcomePage != 'welcome1' ? (guide.guideMenuSelectTextColor) : 'black'),
                                                                'border-radius':'30px'} || {}" style="width: 350px;
                                                                  grid-template-columns: max-content max-content 1fr;">{{item.NM}}</div>


                                                            </td>
                                                        </tr>
                                                    </table>

                                                </td>
vm.scrollCatMenu = function () {
    $location.hash("guide-item-cat-" + vm.selectedGuideIndex);
    $anchorScroll();
    vm.logInfo('scrollCatMenu', 'Scroll Cat Menu Worked Properly.')
  };

How can I make the scrolling process ensure that the entire td element is visible?

expected scrolling

menu that cannot be scrolled

To resolve this, I added $timeout inside my scrollMenu function and performed the operation here, but nothing changed. To equalize the sizes, I increased the size of the td elements, but again, nothing changed. In any case, even if the td edge to be scrolled is visible, anchorScroll does not perform any scrolling operation.

When I add a static empty span with the same ID as the first TD’s ID at the very beginning of the TDs, the page at least opens with the scroll position set to the first menu. I tried the same solution by adding a span after the last TD, but it didn’t work.