@vraxis/osx-components 0.11.3

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.
package/package.json ADDED
@@ -0,0 +1,81 @@
1
+ {
2
+ "name": "@vraxis/osx-components",
3
+ "version": "0.11.3",
4
+ "description": "OS X-inspired web components authored with Vue.",
5
+ "type": "module",
6
+ "sideEffects": [
7
+ "*.css"
8
+ ],
9
+ "files": [
10
+ "bin",
11
+ "dist",
12
+ "skills",
13
+ "types",
14
+ "README.md",
15
+ "LICENSE"
16
+ ],
17
+ "main": "./dist/osx-components.js",
18
+ "module": "./dist/osx-components.js",
19
+ "types": "./types/index.d.ts",
20
+ "bin": {
21
+ "osx-components": "bin/osx-components.mjs"
22
+ },
23
+ "exports": {
24
+ ".": {
25
+ "types": "./types/index.d.ts",
26
+ "import": "./dist/osx-components.js"
27
+ },
28
+ "./theme.css": "./dist/osx-components.css",
29
+ "./skill": "./skills/build-with-osx-components/SKILL.md"
30
+ },
31
+ "scripts": {
32
+ "dev": "vite",
33
+ "build": "vue-tsc -b && vite build",
34
+ "build:site": "vite build --config vite.site.config.ts",
35
+ "test": "node --test test/*.test.mjs",
36
+ "test:consumers": "npm run build && node test/packed-consumer.mjs && node test/framework-builds.mjs",
37
+ "test:browser": "playwright test",
38
+ "test:visual:update": "playwright test --update-snapshots",
39
+ "test:quality": "npm run check && npm run test:consumers && npm run test:browser",
40
+ "check": "npm run test && npm run build",
41
+ "preview": "vite preview",
42
+ "preview:site": "vite preview --config vite.site.config.ts",
43
+ "audit:osx": "node skills/build-with-osx-components/scripts/audit-osx-ui.mjs ."
44
+ },
45
+ "keywords": [
46
+ "web-components",
47
+ "vue",
48
+ "macos",
49
+ "osx",
50
+ "aqua",
51
+ "design-system"
52
+ ],
53
+ "license": "MIT",
54
+ "publishConfig": {
55
+ "access": "public"
56
+ },
57
+ "repository": {
58
+ "type": "git",
59
+ "url": "git+https://github.com/Vequan23/osx-components.git"
60
+ },
61
+ "homepage": "https://github.com/Vequan23/osx-components#readme",
62
+ "bugs": "https://github.com/Vequan23/osx-components/issues",
63
+ "dependencies": {
64
+ "@lucide/vue": "^1.33.0",
65
+ "vue": "^3.5.21"
66
+ },
67
+ "devDependencies": {
68
+ "@axe-core/playwright": "^4.13.0",
69
+ "@playwright/test": "^1.62.1",
70
+ "@sveltejs/vite-plugin-svelte": "^6.2.4",
71
+ "@types/node": "^26.2.0",
72
+ "@vitejs/plugin-react": "^5.2.0",
73
+ "@vitejs/plugin-vue": "^6.0.1",
74
+ "react": "^19.2.8",
75
+ "react-dom": "^19.2.8",
76
+ "svelte": "^5.56.10",
77
+ "typescript": "^5.9.3",
78
+ "vite": "^7.1.3",
79
+ "vue-tsc": "^3.0.8"
80
+ }
81
+ }
@@ -0,0 +1,57 @@
1
+ ---
2
+ name: build-with-osx-components
3
+ description: Build, refactor, or review web interfaces that use the @vraxis/osx-components package and its OS X-inspired custom elements. Use for application shells, dashboards, settings, data tables, agent workbenches, feedback, typography, theming, icons, responsive layouts, accessibility, or migrations from bespoke controls to OSX Components in HTML, Vue, React, Svelte, Astro, and other web projects.
4
+ ---
5
+
6
+ # Build with OSX Components
7
+
8
+ Build cohesive interfaces from the published primitives before creating custom UI. Treat the package as a framework-neutral Custom Elements design system: the host owns application state, data, routing, model calls, tool execution, persistence, and analytics.
9
+
10
+ ## Workflow
11
+
12
+ 1. Inspect the host project before editing.
13
+ - Identify its framework, package manager, entry point, theme root, and existing `@vraxis/osx-components` version.
14
+ - Search for existing OSX Components usage and preserve established composition patterns.
15
+ - Do not install, upgrade, or replace dependencies unless the task authorizes it.
16
+ 2. Choose primitives before writing markup.
17
+ - Read [references/component-selection.md](references/component-selection.md) when selecting or combining components.
18
+ - Inspect `node_modules/@vraxis/osx-components/types/index.d.ts` for the exact installed API. In the library repository, inspect `types/index.d.ts` and `demo/component-docs.ts`.
19
+ - Never invent a component, prop, slot, event, token, or icon name.
20
+ 3. Integrate once at the application boundary.
21
+ - Import `@vraxis/osx-components/theme.css` once.
22
+ - Call `registerOsxComponents()` once in the client entry point.
23
+ - Set `data-osx-theme="aqua"`, `graphite`, or `panther` on a stable ancestor.
24
+ - Read [references/framework-usage.md](references/framework-usage.md) only for the active framework.
25
+ 4. Compose the interface.
26
+ - Read [references/composition-patterns.md](references/composition-patterns.md) for shells, agent workspaces, settings, repository tools, and data-heavy views.
27
+ - Prefer component props and slots over shadow-root overrides.
28
+ - Use `--osx-*` tokens for intentional product-level customization.
29
+ - Keep application behavior outside the components and respond to emitted custom events.
30
+ 5. Verify the finished experience.
31
+ - Read [references/quality-standard.md](references/quality-standard.md).
32
+ - Run the host project's typecheck, tests, and production build.
33
+ - Run `node <skill-directory>/scripts/audit-osx-ui.mjs <project-root>` and address errors. Use `--strict` when warnings should block completion.
34
+ - Exercise keyboard behavior and inspect desktop and mobile layouts in a real browser.
35
+
36
+ ## Non-negotiable rules
37
+
38
+ - Keep rendered text at 12px or larger.
39
+ - Use `<osx-icon>` or component icon props with a supported Lucide name. Do not use emoji, Unicode symbols, or improvised text glyphs as interface icons.
40
+ - Use `<osx-icon-button label="…">` for icon-only actions. Pair unfamiliar compact actions with `<osx-tooltip>`.
41
+ - Prefer native-semantic components over clickable generic containers.
42
+ - Preserve visible focus, keyboard operation, accessible names, textual status, and reduced-motion behavior.
43
+ - Do not convey state with color alone.
44
+ - Do not make Apple affiliation claims or copy Apple assets. Reuse the interaction language and token system only.
45
+ - Do not make components perform hidden network requests, analytics, model calls, or privileged actions. Keep those decisions with the host.
46
+ - Do not expose private reasoning as chain-of-thought. Use `<osx-thinking>` for a concise model-provided progress or reasoning summary.
47
+ - Do not create a new primitive merely to reproduce a published component. Compose existing primitives first.
48
+
49
+ ## Event and data boundary
50
+
51
+ Custom-element events expose Vue event arguments in `event.detail`. Read the first emitted argument with `event.detail[0]` unless the installed type or documentation says otherwise.
52
+
53
+ Assign arrays and objects as DOM properties when possible. JSON attributes remain useful for static HTML examples, but property assignment avoids escaping errors and preserves value types.
54
+
55
+ ## Completion report
56
+
57
+ State which OSX Components were used, any intentional custom CSS or missing primitive, the theme verified, and the checks run. Mention unresolved accessibility, mobile, or API uncertainty explicitly.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Build with OSX Components"
3
+ short_description: "Build consistent interfaces with OSX Components"
4
+ default_prompt: "Use $build-with-osx-components to build this interface from accessible OSX Components primitives."
@@ -0,0 +1,72 @@
1
+ # Component selection
2
+
3
+ Use this guide to choose a primitive. Inspect the installed `types/index.d.ts` before relying on exact props or events.
4
+
5
+ ## Application structure
6
+
7
+ - `osx-app-shell`: full workspace with toolbar, sidebar, main content, composer, inspector, and status areas; opt into accessible side-panel resizing with `resizable`.
8
+ - `osx-window`: bounded window chrome for demos, settings, and focused surfaces.
9
+ - `osx-toolbar`: leading, center, and trailing application actions.
10
+ - `osx-source-list`: Finder-style navigation.
11
+ - `osx-split-view`: primary-detail or stacked responsive panes.
12
+ - `osx-status-bar`: concise connection or activity context.
13
+ - `osx-tabs`: switch among related panels without navigation.
14
+
15
+ ## Actions and inputs
16
+
17
+ - `osx-button`: visible text action, optionally reinforced by a Lucide icon.
18
+ - `osx-icon-button`: compact icon-only action with a required accessible label.
19
+ - `osx-text-field`: labeled single-line text, email, password, search, telephone, or URL input with validation and an optional icon.
20
+ - `osx-textarea`: labeled multi-line input with validation and controlled resize behavior.
21
+ - `osx-select`: native single-choice input with comma-separated labels or structured options.
22
+ - `osx-radio-group`: native single-choice group when every option should stay visible; use its card variant for choices with supporting descriptions.
23
+ - `osx-checkbox`: independent or multi-select choice.
24
+ - `osx-toggle`: immediate on/off setting.
25
+ - `osx-segmented-control`: compact single selection among a few views.
26
+ - `osx-menu` and `osx-menu-item`: keyboard-oriented command collection.
27
+
28
+ ## Data and repository views
29
+
30
+ - `osx-data-table`: searching, sorting, pagination, selection, loading, row activation, and server orchestration.
31
+ - `osx-table`: lightweight native table when advanced orchestration is unnecessary.
32
+ - `osx-file-tree`: filterable repository hierarchy with Git status.
33
+ - `osx-diff-viewer`: unified or split patch evidence.
34
+ - `osx-terminal`: command, output, state, and bounded execution controls.
35
+ - `osx-progress`: determinate or indeterminate progress with a measurable task.
36
+
37
+ ## Agent interfaces
38
+
39
+ - `osx-agent-composer`: prompt entry, submission, busy state, model context, and stop action.
40
+ - `osx-agent-message`: user, assistant, system, streaming, and error messages.
41
+ - `osx-agent-run-status`: run-level plan, work, verify, completion, and failure lifecycle.
42
+ - `osx-agent-approval`: explicit human approval for a bounded action.
43
+ - `osx-thinking`: collapsible reasoning summary or progress trace.
44
+ - `osx-plan`: task steps with pending, active, done, failed, and skipped states.
45
+ - `osx-tool-call`: expandable tool activity.
46
+ - `osx-artifact`: generated file, document, or code output.
47
+ - `osx-markdown`: safe streaming Markdown.
48
+ - `osx-citation` and `osx-source-panel`: coordinated grounded sources.
49
+
50
+ ## Feedback and overlays
51
+
52
+ - `osx-alert`: persistent contextual feedback.
53
+ - `osx-toast`: transient completion or failure notice.
54
+ - `osx-empty-state`: absence of data plus an optional recovery action.
55
+ - `osx-spinner`: compact indeterminate activity.
56
+ - `osx-shimmer` and `osx-skeleton`: layout-preserving loading placeholders.
57
+ - `osx-dialog`: centered modal decision or focused content.
58
+ - `osx-sheet`: window-attached confirmation or task surface.
59
+ - `osx-popover`: anchored contextual content.
60
+ - `osx-tooltip`: supplemental hover and focus hint, never an action's only label.
61
+
62
+ ## Content and identity
63
+
64
+ - `osx-heading`, `osx-copy`, and `osx-link`: semantic typography and navigation.
65
+ - `osx-icon`: supported Lucide glyph.
66
+ - `osx-avatar`: person or agent identity and presence.
67
+ - `osx-badge`: compact category, count, or status.
68
+ - `osx-ecosystem-card`: transparent first-party ecosystem discovery with host-owned tracking.
69
+
70
+ ## Selection rule
71
+
72
+ Use the smallest component that owns the needed semantics. Compose multiple primitives for product-specific layouts; create custom CSS only for arrangement and product identity that tokens and slots do not cover.
@@ -0,0 +1,47 @@
1
+ # Composition patterns
2
+
3
+ ## Product workspace
4
+
5
+ Use `osx-app-shell` as the layout owner. Put primary navigation in `sidebar`, persistent actions in `toolbar`, contextual detail in `inspector`, creation input in `composer`, and concise state in `status`. Keep page-specific content in the default slot.
6
+
7
+ Set `resizable` when desktop users benefit from changing the navigation or inspector width. Configure the four pixel bounds for the product's content, listen for `panel-resize`, and let the host persist the preference. Resize handles disappear when the shell stacks on narrow screens.
8
+
9
+ Do not repeat project identity, model identity, or run status in multiple shell regions. Give each fact one stable home.
10
+
11
+ ## Agent workbench
12
+
13
+ Compose:
14
+
15
+ 1. `osx-agent-message` for the conversation.
16
+ 2. `osx-thinking` for an optional progress summary.
17
+ 3. `osx-plan` for explicit task steps.
18
+ 4. `osx-tool-call` for bounded actions and inspectable output.
19
+ 5. `osx-artifact` or `osx-diff-viewer` for generated work.
20
+ 6. `osx-agent-approval` before consequential actions.
21
+ 7. `osx-agent-composer` as the persistent input.
22
+
23
+ Show the response immediately after completion. Keep raw tool traces in activity, not in the primary response body. Never manufacture changes when the agent answered with analysis only.
24
+
25
+ ## Repository comprehension
26
+
27
+ Use `osx-file-tree` beside `osx-diff-viewer` or an artifact preview. Use a resizable `osx-split-view` when both panes need sustained attention. Put verification output in `osx-terminal`; summarize the result in an alert or status bar rather than duplicating the complete log.
28
+
29
+ ## Settings
30
+
31
+ Use semantic headings and copy, `osx-text-field` for single-line values, and `osx-textarea` for multi-line content. Use `osx-radio-group` when a mutually exclusive choice should stay visible, `osx-select` when space matters, toggles for immediate binary settings, checkboxes for independent selection, and segmented controls for switching among a few views. Put validation text in the controls' `error` props so it remains programmatically associated. Use a sheet or dialog only when the decision must interrupt the current workflow.
32
+
33
+ ## Data-heavy views
34
+
35
+ Use `osx-data-table` for application records that need search, sorting, selection, or pagination. Use server mode when the host owns remote filtering and pagination. Keep row actions explicit and avoid making every cell independently clickable.
36
+
37
+ Pair the table with:
38
+
39
+ - `osx-empty-state` before data exists.
40
+ - `osx-skeleton` when the table shape is not yet known.
41
+ - the table's loading state when rows are refreshing in place.
42
+ - `osx-alert` for recoverable fetch errors.
43
+ - `osx-toast` for completed mutations.
44
+
45
+ ## Responsive hierarchy
46
+
47
+ Preserve task order on narrow screens. Collapse secondary navigation and inspectors before compressing primary content. Allow data tables, diffs, terminals, and file trees to scroll within their own bounded regions. Do not reduce typography below 12px to make dense layouts fit.
@@ -0,0 +1,105 @@
1
+ # Framework usage
2
+
3
+ Register the custom elements once and import the theme once. Avoid invoking `registerOsxComponents()` from every view or component.
4
+
5
+ ## HTML and framework-neutral entry points
6
+
7
+ ```html
8
+ <script type="module">
9
+ import { registerOsxComponents } from "@vraxis/osx-components";
10
+ import "@vraxis/osx-components/theme.css";
11
+ registerOsxComponents();
12
+ </script>
13
+
14
+ <main data-osx-theme="panther">
15
+ <osx-button variant="primary" icon="sparkle">Create</osx-button>
16
+ </main>
17
+ ```
18
+
19
+ For structured data, assign the DOM property:
20
+
21
+ ```js
22
+ const table = document.querySelector("osx-data-table");
23
+ table.columns = columns;
24
+ table.rows = rows;
25
+ table.addEventListener("selection-change", (event) => {
26
+ selectedKeys = event.detail[0];
27
+ });
28
+ ```
29
+
30
+ ## Vue
31
+
32
+ Register from the client entry point:
33
+
34
+ ```ts
35
+ import { registerOsxComponents } from "@vraxis/osx-components";
36
+ import "@vraxis/osx-components/theme.css";
37
+
38
+ registerOsxComponents();
39
+ ```
40
+
41
+ Vue templates can bind complex properties directly:
42
+
43
+ ```vue
44
+ <osx-data-table
45
+ :columns="columns"
46
+ :rows="rows"
47
+ selectable
48
+ @selection-change="selected = $event.detail[0]"
49
+ />
50
+ ```
51
+
52
+ Keep Vue application state outside the custom element. Treat the emitted event as the request to update that state.
53
+
54
+ ## React
55
+
56
+ Register in a client-only entry module. React 19 handles custom-element properties and events more naturally, but use a ref when a framework or toolchain serializes complex values as attributes.
57
+
58
+ ```tsx
59
+ import { useEffect, useRef } from "react";
60
+ import { registerOsxComponents } from "@vraxis/osx-components";
61
+ import "@vraxis/osx-components/theme.css";
62
+
63
+ registerOsxComponents();
64
+
65
+ export function Results({ rows, columns }) {
66
+ const ref = useRef<HTMLElement & { rows: unknown[]; columns: unknown[] }>(null);
67
+ useEffect(() => {
68
+ if (!ref.current) return;
69
+ ref.current.rows = rows;
70
+ ref.current.columns = columns;
71
+ }, [rows, columns]);
72
+ return <osx-data-table ref={ref} label="Results" />;
73
+ }
74
+ ```
75
+
76
+ Use `addEventListener` with cleanup when React's event typing does not recognize a custom event.
77
+
78
+ ## Svelte
79
+
80
+ Register once in a client entry or `onMount`, then assign complex properties through a bound element when necessary.
81
+
82
+ ```svelte
83
+ <script lang="ts">
84
+ import { onMount } from "svelte";
85
+ import { registerOsxComponents } from "@vraxis/osx-components";
86
+ import "@vraxis/osx-components/theme.css";
87
+ onMount(registerOsxComponents);
88
+ </script>
89
+
90
+ <osx-button variant="primary">Save</osx-button>
91
+ ```
92
+
93
+ ## SSR environments
94
+
95
+ Call `registerOsxComponents()` only in the browser. Use the framework's client entry, client-only boundary, or mount hook so `customElements` is available. Render stable fallback content where hydration behavior matters.
96
+
97
+ ## Theme boundary
98
+
99
+ Apply one theme to the highest stable product container:
100
+
101
+ ```html
102
+ <div data-osx-theme="aqua">...</div>
103
+ ```
104
+
105
+ Nest a different theme only for a deliberate preview or isolated surface. Prefer `--osx-*` token overrides on the product container over penetrating component shadow roots.
@@ -0,0 +1,44 @@
1
+ # Quality standard
2
+
3
+ ## Visual consistency
4
+
5
+ - Use one theme boundary and the shared `--osx-*` tokens.
6
+ - Use published spacing, radii, borders, and control sizes before adding custom values.
7
+ - Keep icon geometry consistent through `osx-icon` and supported component icon props.
8
+ - Avoid redundant headers, duplicate status labels, and decorative controls without a task.
9
+ - Keep every rendered font size at 12px or larger.
10
+
11
+ ## Interaction
12
+
13
+ - Make the primary action obvious and singular within each decision surface.
14
+ - Clear forms after successful submission when retention would cause accidental duplicates.
15
+ - Show immediate feedback for save, submit, copy, connection, and destructive operations.
16
+ - Return focus after dismissing a modal or popover.
17
+ - Ensure loading states explain what is happening and do not trap the user.
18
+ - Keep resizable panels operable by pointer and keyboard, expose their current value, and enforce practical minimum and maximum widths.
19
+
20
+ ## Accessibility
21
+
22
+ - Use semantic components and landmarks.
23
+ - Provide visible labels for inputs and text labels or accessible names for every action.
24
+ - Associate form hints and validation errors with their native controls, and never rely on a red border alone.
25
+ - Use `osx-icon-button` only with `label`.
26
+ - Keep status textual; color and icons may reinforce it but cannot be the only signal.
27
+ - Verify focus visibility and logical keyboard order.
28
+ - Respect reduced motion and sufficient contrast in Aqua, Graphite, and Panther where applicable.
29
+
30
+ ## Responsive behavior
31
+
32
+ - Test at a desktop width and at 390px or narrower.
33
+ - Check the document and each dense component for unintended horizontal overflow.
34
+ - Stack toolbars and action groups deliberately rather than squeezing labels.
35
+ - Keep interactive targets usable by touch.
36
+
37
+ ## Technical verification
38
+
39
+ 1. Run the host typecheck and tests.
40
+ 2. Run the production build.
41
+ 3. Run `audit-osx-ui.mjs` against the changed source tree.
42
+ 4. Exercise critical interactions in a browser.
43
+ 5. Check the browser console for new errors and warnings.
44
+ 6. Report any missing primitive or intentional native control instead of silently duplicating the design system.
@@ -0,0 +1,71 @@
1
+ #!/usr/bin/env node
2
+ import { readFile, readdir } from "node:fs/promises";
3
+ import { extname, join, relative, resolve } from "node:path";
4
+
5
+ const args = process.argv.slice(2);
6
+ const strict = args.includes("--strict");
7
+ const json = args.includes("--json");
8
+ const target = resolve(args.find((arg) => !arg.startsWith("--")) || process.cwd());
9
+ const ignored = new Set(["__tests__", "build", "coverage", "dist", "node_modules", "site-dist", "skills", "test", "tests"]);
10
+ const extensions = new Set([".css", ".html", ".js", ".jsx", ".less", ".mjs", ".sass", ".scss", ".svelte", ".ts", ".tsx", ".vue"]);
11
+ const rawGlyphs = /[✓✔✕✖❯❮▶◀↻⚙⌘◉◆]/u;
12
+ const findings = [];
13
+
14
+ async function filesIn(directory) {
15
+ const files = [];
16
+ for (const entry of await readdir(directory, { withFileTypes: true })) {
17
+ if (entry.isDirectory() && (entry.name.startsWith(".") || ignored.has(entry.name))) continue;
18
+ const path = join(directory, entry.name);
19
+ if (entry.isDirectory()) files.push(...await filesIn(path));
20
+ else if (extensions.has(extname(entry.name))) files.push(path);
21
+ }
22
+ return files;
23
+ }
24
+
25
+ function lineOf(source, index) {
26
+ return source.slice(0, index).split("\n").length;
27
+ }
28
+
29
+ function add(file, source, match, severity, rule, message) {
30
+ findings.push({ severity, rule, file: relative(target, file), line: lineOf(source, match.index), message });
31
+ }
32
+
33
+ function isKeyboardShortcutGlyph(source, index) {
34
+ for (const match of source.matchAll(/\bshortcut\s*=\s*(["'])[\s\S]*?\1/gi)) {
35
+ if (index >= match.index && index < match.index + match[0].length) return true;
36
+ }
37
+ const lineStart = source.lastIndexOf("\n", index) + 1;
38
+ const lineEnd = source.indexOf("\n", index);
39
+ if (/\.output\s*=/.test(source.slice(lineStart, lineEnd < 0 ? source.length : lineEnd))) return true;
40
+ const before = source.slice(0, index);
41
+ return before.lastIndexOf("<kbd") > before.lastIndexOf("</kbd>");
42
+ }
43
+
44
+ for (const file of await filesIn(target)) {
45
+ const source = await readFile(file, "utf8");
46
+ for (const match of source.matchAll(/font-size\s*:\s*(\d+(?:\.\d+)?)px/gi)) {
47
+ if (Number(match[1]) < 12) add(file, source, match, "error", "minimum-font-size", `Font size ${match[1]}px is below the 12px minimum.`);
48
+ }
49
+ for (const match of source.matchAll(/font\s*:\s*[^;{}]*?(\d+(?:\.\d+)?)px(?:\s*\/[^;{}\s]+)?/gi)) {
50
+ if (Number(match[1]) < 12) add(file, source, match, "error", "minimum-font-size", `Font shorthand uses ${match[1]}px, below the 12px minimum.`);
51
+ }
52
+ for (const match of source.matchAll(/<osx-icon-button\b[^>]*>/gis)) {
53
+ if (!/(?:^|\s)(?::?label|aria-label)\s*=/.test(match[0])) add(file, source, match, "error", "icon-button-label", "osx-icon-button requires a visible or accessible label prop.");
54
+ }
55
+ for (const match of source.matchAll(/<osx-(?:text-field|textarea|select|radio-group)\b[^>]*>/gis)) {
56
+ if (!/(?:^|\s):?label\s*=/.test(match[0])) add(file, source, match, "error", "form-control-label", "OSX form controls require a visible label prop.");
57
+ }
58
+ for (const match of source.matchAll(rawGlyphs.global ? rawGlyphs : new RegExp(rawGlyphs.source, "gu"))) {
59
+ if (isKeyboardShortcutGlyph(source, match.index)) continue;
60
+ add(file, source, match, "warning", "raw-interface-glyph", `Replace raw interface glyph ${JSON.stringify(match[0])} with osx-icon or a component icon prop.`);
61
+ }
62
+ }
63
+
64
+ const errors = findings.filter((finding) => finding.severity === "error");
65
+ const warnings = findings.filter((finding) => finding.severity === "warning");
66
+ if (json) console.log(JSON.stringify({ target, errors: errors.length, warnings: warnings.length, findings }, null, 2));
67
+ else {
68
+ for (const finding of findings) console.log(`${finding.severity.toUpperCase()} ${finding.file}:${finding.line} [${finding.rule}] ${finding.message}`);
69
+ console.log(`OSX Components audit: ${errors.length} error(s), ${warnings.length} warning(s).`);
70
+ }
71
+ process.exitCode = errors.length || (strict && warnings.length) ? 1 : 0;