@vit-foundation/ui 0.24.0 → 0.24.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -9,16 +9,32 @@
9
9
  let { size = 32, withWordmark = false }: Props = $props();
10
10
  </script>
11
11
 
12
+ <!--
13
+ The mark is ALWAYS decorative. It carries no accessible name of its own, in
14
+ either branch, because at every call site something else already supplies
15
+ one — and when it tried, it doubled.
16
+
17
+ `withWordmark` used to flip three accessibility facts together:
18
+ `aria-hidden`, `role="img"` and the presence of `<title>`. With the wordmark
19
+ on, the mark was named "Brain VIT" AND the wordmark rendered the same string
20
+ beside it, so a screen reader announced the name twice on all three of
21
+ Brain's sign-in pages. Inverting the branch does not help: with the wordmark
22
+ off, the rail already names it through `<a aria-label="Home">` and the print
23
+ sheet sits it beside an `<h1>`, so naming the mark there doubles at the other
24
+ end.
25
+
26
+ Which leaves one honest rule — never name it — and the naming stays where
27
+ the context is: the visible wordmark below, the anchor around it, or the
28
+ heading beside it. `Logo.svelte.test.ts` pins both branches.
29
+ -->
12
30
  <span class="logo">
13
31
  <svg
14
32
  viewBox="0 0 48 56"
15
33
  width={size * (48 / 56)}
16
34
  height={size}
17
- aria-hidden={withWordmark ? undefined : true}
18
- role={withWordmark ? 'img' : undefined}
35
+ aria-hidden="true"
19
36
  focusable="false"
20
37
  >
21
- {#if withWordmark}<title>Brain VIT</title>{/if}
22
38
  <path
23
39
  d="M25 2c11.6 0 21 9.4 21 21 0 6.9-3.3 13-8.5 16.8V54H17v-9h-4.5A4.5 4.5 0 0 1 8 40.5V34H4.2c-1.7 0-2.7-1.9-1.7-3.3L8 22.4C9 11 16.2 2 25 2Z"
24
40
  fill="currentColor"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vit-foundation/ui",
3
- "version": "0.24.0",
3
+ "version": "0.24.2",
4
4
  "scripts": {
5
5
  "dev": "vite dev",
6
6
  "build": "vite build && npm run prepack",
@@ -25,7 +25,8 @@
25
25
  "!dist/**/*.spec.*",
26
26
  "!dist/fixtures.*",
27
27
  "!dist/**/stories/**",
28
- "!dist/**/tests/**"
28
+ "!dist/**/tests/**",
29
+ "!dist/testing/imports.*"
29
30
  ],
30
31
  "sideEffects": [
31
32
  "**/*.css"
@@ -1,51 +0,0 @@
1
- /**
2
- * What a source scan needs to see, and the anchors that keep it honest.
3
- *
4
- * Two guards in this package walk the source: `contract.test.ts` follows the
5
- * relative import graph beneath `./contract`, and `no-app-imports.test.ts`
6
- * scans every module for an app virtual specifier. They ask different
7
- * questions of the same rule — WHICH MODULES DOES THIS ONE NAME — and each
8
- * used to answer it with a pattern of its own. `contract.test.ts` found the
9
- * defect in its copy and fixed it there:
10
- *
11
- * "THREE import forms, because two of them used to be invisible here. The
12
- * pattern required the `from` keyword, so a side-effect import and a
13
- * dynamic one both walked past a guard whose whole job is to see them."
14
- *
15
- * The other copy was not fixed and still required `from`, so a dynamic import
16
- * of an $app specifier walked past the gate that decides whether this package
17
- * is publishable. Copying the lesson a third time is how a guard
18
- * starts missing things again; the grammar lives here instead, and each guard
19
- * filters the specifiers it cares about.
20
- */
21
- /**
22
- * Every module specifier a source file names, in all three forms a bundler
23
- * follows: `from '…'` (import and re-export alike), a bare side-effect
24
- * `import '…'`, and a dynamic `import('…')`.
25
- *
26
- * A type-only import is reported like any other. That is deliberate, and it
27
- * is `contract.test.ts`'s standing argument: erasure is a build-time fact, and
28
- * a pattern that has to understand `import type` is a pattern with a second
29
- * way to be wrong.
30
- */
31
- export declare function importSpecifiers(source: string): readonly string[];
32
- /**
33
- * Every `.ts` and `.svelte` file beneath `root`, and the ones the walk MUST
34
- * find.
35
- *
36
- * `mustReach` is a required argument for the reason `contract.test.ts` gives
37
- * at length: an assertion over an empty list passes. `expect(offenders)
38
- * .toEqual([])` is a clean bill of health over a walk that enumerated nothing
39
- * — a directory renamed, a `readdirSync` that threw and was caught upstream,
40
- * an entry filter that stopped matching — and a safety net that can narrow in
41
- * silence reproduces the defect it exists to prevent. fndvit-website's
42
- * `src/lib/testing/source-scan.ts` settled the shape: a scan cannot walk the
43
- * tree without saying what it must find.
44
- *
45
- * Anchors are relative to `root` with `/` separators, so one representation
46
- * crosses this interface and an anchor cannot silently fail to match an
47
- * absolute path. A FLOOR was the alternative and is the thing being replaced:
48
- * a walk that quietly stopped seeing two thirds of the tree clears any floor
49
- * worth setting.
50
- */
51
- export declare function sourceFiles(root: string, mustReach: readonly string[]): readonly string[];
@@ -1,70 +0,0 @@
1
- import { readdirSync } from 'node:fs';
2
- import { join, relative } from 'node:path';
3
- /**
4
- * What a source scan needs to see, and the anchors that keep it honest.
5
- *
6
- * Two guards in this package walk the source: `contract.test.ts` follows the
7
- * relative import graph beneath `./contract`, and `no-app-imports.test.ts`
8
- * scans every module for an app virtual specifier. They ask different
9
- * questions of the same rule — WHICH MODULES DOES THIS ONE NAME — and each
10
- * used to answer it with a pattern of its own. `contract.test.ts` found the
11
- * defect in its copy and fixed it there:
12
- *
13
- * "THREE import forms, because two of them used to be invisible here. The
14
- * pattern required the `from` keyword, so a side-effect import and a
15
- * dynamic one both walked past a guard whose whole job is to see them."
16
- *
17
- * The other copy was not fixed and still required `from`, so a dynamic import
18
- * of an $app specifier walked past the gate that decides whether this package
19
- * is publishable. Copying the lesson a third time is how a guard
20
- * starts missing things again; the grammar lives here instead, and each guard
21
- * filters the specifiers it cares about.
22
- */
23
- /**
24
- * Every module specifier a source file names, in all three forms a bundler
25
- * follows: `from '…'` (import and re-export alike), a bare side-effect
26
- * `import '…'`, and a dynamic `import('…')`.
27
- *
28
- * A type-only import is reported like any other. That is deliberate, and it
29
- * is `contract.test.ts`'s standing argument: erasure is a build-time fact, and
30
- * a pattern that has to understand `import type` is a pattern with a second
31
- * way to be wrong.
32
- */
33
- export function importSpecifiers(source) {
34
- return [...source.matchAll(/(?:\bfrom|\bimport)\s*\(?\s*['"]([^'"]*)['"]/g)].map(([, specifier]) => specifier);
35
- }
36
- /**
37
- * Every `.ts` and `.svelte` file beneath `root`, and the ones the walk MUST
38
- * find.
39
- *
40
- * `mustReach` is a required argument for the reason `contract.test.ts` gives
41
- * at length: an assertion over an empty list passes. `expect(offenders)
42
- * .toEqual([])` is a clean bill of health over a walk that enumerated nothing
43
- * — a directory renamed, a `readdirSync` that threw and was caught upstream,
44
- * an entry filter that stopped matching — and a safety net that can narrow in
45
- * silence reproduces the defect it exists to prevent. fndvit-website's
46
- * `src/lib/testing/source-scan.ts` settled the shape: a scan cannot walk the
47
- * tree without saying what it must find.
48
- *
49
- * Anchors are relative to `root` with `/` separators, so one representation
50
- * crosses this interface and an anchor cannot silently fail to match an
51
- * absolute path. A FLOOR was the alternative and is the thing being replaced:
52
- * a walk that quietly stopped seeing two thirds of the tree clears any floor
53
- * worth setting.
54
- */
55
- export function sourceFiles(root, mustReach) {
56
- const walk = (dir) => readdirSync(dir, { withFileTypes: true }).flatMap((entry) => {
57
- const path = join(dir, entry.name);
58
- if (entry.isDirectory())
59
- return walk(path);
60
- return /\.(ts|svelte)$/.test(entry.name) ? [path] : [];
61
- });
62
- const files = walk(root);
63
- const found = new Set(files.map((file) => relative(root, file).replaceAll('\\', '/')));
64
- const missing = mustReach.filter((anchor) => !found.has(anchor));
65
- if (missing.length > 0) {
66
- throw new Error(`the source scan enumerated ${files.length} files but not ${missing.join(', ')} — ` +
67
- 'either the module moved or the walk stopped seeing it');
68
- }
69
- return files;
70
- }