@viglet/viglet-design-system 2026.3.10 → 2026.3.12
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/README.md +323 -36
- package/consumers.json +186 -0
- package/dist/badge-locale-1_BmNTro.cjs +1 -0
- package/dist/badge-locale-Bx7m7tg2.js +501 -0
- package/dist/bento/bento-actions-menu.d.ts +8 -0
- package/dist/bento/bento-actions-menu.d.ts.map +1 -1
- package/dist/bento/bento-back-to-top.d.ts +9 -1
- package/dist/bento/bento-back-to-top.d.ts.map +1 -1
- package/dist/bento/bento-command-palette.d.ts +12 -0
- package/dist/bento/bento-command-palette.d.ts.map +1 -1
- package/dist/bento/bento-data-table.d.ts +81 -0
- package/dist/bento/bento-data-table.d.ts.map +1 -0
- package/dist/bento/bento-diff.d.ts +41 -0
- package/dist/bento/bento-diff.d.ts.map +1 -0
- package/dist/bento/bento-empty-state.d.ts +8 -1
- package/dist/bento/bento-empty-state.d.ts.map +1 -1
- package/dist/bento/bento-entity-shell.d.ts.map +1 -1
- package/dist/bento/bento-filter-bar.d.ts +60 -0
- package/dist/bento/bento-filter-bar.d.ts.map +1 -0
- package/dist/bento/bento-form-section.d.ts +10 -3
- package/dist/bento/bento-form-section.d.ts.map +1 -1
- package/dist/bento/bento-inline-edit.d.ts.map +1 -1
- package/dist/bento/bento-nav-rail.d.ts +13 -13
- package/dist/bento/bento-nav-rail.d.ts.map +1 -1
- package/dist/bento/bento-palette-trigger.d.ts +18 -0
- package/dist/bento/bento-palette-trigger.d.ts.map +1 -0
- package/dist/bento/bento-section-chrome.d.ts +17 -42
- package/dist/bento/bento-section-chrome.d.ts.map +1 -1
- package/dist/bento/bento-shell-shortcuts.d.ts +67 -0
- package/dist/bento/bento-shell-shortcuts.d.ts.map +1 -0
- package/dist/bento/bento-shell.d.ts +53 -0
- package/dist/bento/bento-shell.d.ts.map +1 -0
- package/dist/bento/bento-shortcuts-dialog.d.ts +9 -7
- package/dist/bento/bento-shortcuts-dialog.d.ts.map +1 -1
- package/dist/bento/bento-status-marker.d.ts +5 -2
- package/dist/bento/bento-status-marker.d.ts.map +1 -1
- package/dist/bento/bento-user-menu.d.ts +9 -8
- package/dist/bento/bento-user-menu.d.ts.map +1 -1
- package/dist/bento/bento-version-rail.d.ts +31 -0
- package/dist/bento/bento-version-rail.d.ts.map +1 -0
- package/dist/bento/index.d.ts +14 -5
- package/dist/bento/index.d.ts.map +1 -1
- package/dist/bento.cjs +5 -1
- package/dist/bento.css +70 -4
- package/dist/bento.es.js +1642 -625
- package/dist/catalogue.json +5349 -0
- package/dist/components/app-footer.d.ts +7 -0
- package/dist/components/app-footer.d.ts.map +1 -1
- package/dist/components/backend-status.d.ts +19 -11
- package/dist/components/backend-status.d.ts.map +1 -1
- package/dist/components/badge-colorful.d.ts +4 -0
- package/dist/components/badge-colorful.d.ts.map +1 -1
- package/dist/components/badge-locale.d.ts +7 -0
- package/dist/components/badge-locale.d.ts.map +1 -1
- package/dist/components/error-boundary.d.ts +15 -13
- package/dist/components/error-boundary.d.ts.map +1 -1
- package/dist/components/language-select.d.ts +8 -0
- package/dist/components/language-select.d.ts.map +1 -1
- package/dist/components/login/login.d.ts +27 -0
- package/dist/components/login/login.d.ts.map +1 -1
- package/dist/components/mode-toggle.d.ts +9 -0
- package/dist/components/mode-toggle.d.ts.map +1 -1
- package/dist/components/nav-secondary.d.ts +7 -0
- package/dist/components/nav-secondary.d.ts.map +1 -1
- package/dist/components/router/dialog.delete.d.ts +8 -0
- package/dist/components/router/dialog.delete.d.ts.map +1 -1
- package/dist/components/router/gradient-button-link.d.ts +6 -0
- package/dist/components/router/gradient-button-link.d.ts.map +1 -1
- package/dist/components/router/index.d.ts +0 -11
- package/dist/components/router/index.d.ts.map +1 -1
- package/dist/components/router/loading-provider.d.ts +4 -0
- package/dist/components/router/loading-provider.d.ts.map +1 -1
- package/dist/components/startup-first/startup-first.d.ts +29 -0
- package/dist/components/startup-first/startup-first.d.ts.map +1 -1
- package/dist/components/ui/accordion.d.ts +17 -0
- package/dist/components/ui/accordion.d.ts.map +1 -1
- package/dist/components/ui/avatar.d.ts +14 -0
- package/dist/components/ui/avatar.d.ts.map +1 -1
- package/dist/components/ui/badge.d.ts +6 -0
- package/dist/components/ui/badge.d.ts.map +1 -1
- package/dist/components/ui/breadcrumb.d.ts +25 -0
- package/dist/components/ui/breadcrumb.d.ts.map +1 -1
- package/dist/components/ui/button.d.ts +15 -1
- package/dist/components/ui/button.d.ts.map +1 -1
- package/dist/components/ui/card.d.ts +27 -0
- package/dist/components/ui/card.d.ts.map +1 -1
- package/dist/components/ui/checkbox.d.ts +4 -0
- package/dist/components/ui/checkbox.d.ts.map +1 -1
- package/dist/components/ui/dialog.d.ts +36 -0
- package/dist/components/ui/dialog.d.ts.map +1 -1
- package/dist/components/ui/drawer.d.ts +35 -0
- package/dist/components/ui/drawer.d.ts.map +1 -1
- package/dist/components/ui/dropdown-menu.d.ts +53 -0
- package/dist/components/ui/dropdown-menu.d.ts.map +1 -1
- package/dist/components/ui/floating-formulas-bg.d.ts +8 -0
- package/dist/components/ui/floating-formulas-bg.d.ts.map +1 -1
- package/dist/components/ui/form-actions.d.ts +7 -0
- package/dist/components/ui/form-actions.d.ts.map +1 -1
- package/dist/components/ui/form-item-two-columns.d.ts +7 -0
- package/dist/components/ui/form-item-two-columns.d.ts.map +1 -1
- package/dist/components/ui/form.d.ts +26 -1
- package/dist/components/ui/form.d.ts.map +1 -1
- package/dist/components/ui/glass-card.d.ts +13 -14
- package/dist/components/ui/glass-card.d.ts.map +1 -1
- package/dist/components/ui/gradient-button.d.ts +15 -1
- package/dist/components/ui/gradient-button.d.ts.map +1 -1
- package/dist/components/ui/gradient-switch.d.ts +6 -0
- package/dist/components/ui/gradient-switch.d.ts.map +1 -1
- package/dist/components/ui/hover-card.d.ts +14 -0
- package/dist/components/ui/hover-card.d.ts.map +1 -1
- package/dist/components/ui/index.d.ts +2 -1
- package/dist/components/ui/index.d.ts.map +1 -1
- package/dist/components/ui/input.d.ts +6 -0
- package/dist/components/ui/input.d.ts.map +1 -1
- package/dist/components/ui/label.d.ts +4 -0
- package/dist/components/ui/label.d.ts.map +1 -1
- package/dist/components/ui/navigation-menu.d.ts +29 -2
- package/dist/components/ui/navigation-menu.d.ts.map +1 -1
- package/dist/components/ui/pagination.d.ts +25 -0
- package/dist/components/ui/pagination.d.ts.map +1 -1
- package/dist/components/ui/popover.d.ts +24 -0
- package/dist/components/ui/popover.d.ts.map +1 -1
- package/dist/components/ui/progress.d.ts +4 -0
- package/dist/components/ui/progress.d.ts.map +1 -1
- package/dist/components/ui/pulse-ring.d.ts +9 -11
- package/dist/components/ui/pulse-ring.d.ts.map +1 -1
- package/dist/components/ui/resizable.d.ts +11 -0
- package/dist/components/ui/resizable.d.ts.map +1 -1
- package/dist/components/ui/section-card.d.ts +9 -0
- package/dist/components/ui/section-card.d.ts.map +1 -1
- package/dist/components/ui/select.d.ts +36 -0
- package/dist/components/ui/select.d.ts.map +1 -1
- package/dist/components/ui/separator.d.ts +4 -0
- package/dist/components/ui/separator.d.ts.map +1 -1
- package/dist/components/ui/sheet.d.ts +29 -0
- package/dist/components/ui/sheet.d.ts.map +1 -1
- package/dist/components/ui/sidebar.d.ts +83 -0
- package/dist/components/ui/sidebar.d.ts.map +1 -1
- package/dist/components/ui/skeleton.d.ts +4 -0
- package/dist/components/ui/skeleton.d.ts.map +1 -1
- package/dist/components/ui/slider.d.ts +4 -0
- package/dist/components/ui/slider.d.ts.map +1 -1
- package/dist/components/ui/sonner.d.ts +6 -2
- package/dist/components/ui/sonner.d.ts.map +1 -1
- package/dist/components/ui/stepper.d.ts +8 -0
- package/dist/components/ui/stepper.d.ts.map +1 -1
- package/dist/components/ui/sticky-save-bar.d.ts +7 -0
- package/dist/components/ui/sticky-save-bar.d.ts.map +1 -1
- package/dist/components/ui/switch.d.ts +4 -0
- package/dist/components/ui/switch.d.ts.map +1 -1
- package/dist/components/ui/table.d.ts +31 -0
- package/dist/components/ui/table.d.ts.map +1 -1
- package/dist/components/ui/tabs.d.ts +16 -0
- package/dist/components/ui/tabs.d.ts.map +1 -1
- package/dist/components/ui/textarea.d.ts +4 -0
- package/dist/components/ui/textarea.d.ts.map +1 -1
- package/dist/components/ui/toggle-group.d.ts +7 -0
- package/dist/components/ui/toggle-group.d.ts.map +1 -1
- package/dist/components/ui/toggle.d.ts +4 -0
- package/dist/components/ui/toggle.d.ts.map +1 -1
- package/dist/components/ui/tooltip.d.ts +18 -0
- package/dist/components/ui/tooltip.d.ts.map +1 -1
- package/dist/components/ui/tree.d.ts +60 -0
- package/dist/components/ui/tree.d.ts.map +1 -0
- package/dist/components/ui/user-avatar.d.ts +2 -1
- package/dist/components/ui/user-avatar.d.ts.map +1 -1
- package/dist/components/ui/viglet-assistant.d.ts +71 -28
- package/dist/components/ui/viglet-assistant.d.ts.map +1 -1
- package/dist/components/ui/viglet-avatar.d.ts +14 -12
- package/dist/components/ui/viglet-avatar.d.ts.map +1 -1
- package/dist/contexts/breadcrumb.context.d.ts +7 -0
- package/dist/contexts/breadcrumb.context.d.ts.map +1 -1
- package/dist/contexts/user.context.d.ts +8 -0
- package/dist/contexts/user.context.d.ts.map +1 -1
- package/dist/exports.json +344 -28
- package/dist/i18n/index.d.ts +94 -0
- package/dist/i18n/index.d.ts.map +1 -1
- package/dist/i18n/locales/en/assistant.json.d.ts +4 -1
- package/dist/i18n/locales/en/bento.json.d.ts +45 -1
- package/dist/i18n/locales/pt/assistant.json.d.ts +4 -1
- package/dist/i18n/locales/pt/bento.json.d.ts +45 -1
- package/dist/i18n.cjs +1 -1
- package/dist/i18n.es.js +98 -4
- package/dist/index.cjs +1 -1
- package/dist/index.es.js +2094 -913
- package/dist/lib/busy.d.ts +26 -0
- package/dist/lib/busy.d.ts.map +1 -0
- package/dist/lib/corner-slot.d.ts +15 -0
- package/dist/lib/corner-slot.d.ts.map +1 -0
- package/dist/{loading-provider-E3fbcekM.js → loading-provider-D-_5G-08.js} +71 -69
- package/dist/loading-provider-E4tIG9BM.cjs +1 -0
- package/dist/preset.css +7 -10
- package/dist/router.cjs +1 -1
- package/dist/router.es.js +2 -776
- package/dist/user.context-BXQ7lgg5.js +815 -0
- package/dist/user.context-D01CI8gq.cjs +1 -0
- package/dist/viglet-design-system.css +1 -1
- package/docs/BENTO-AUTHORING.md +61 -9
- package/package.json +13 -2
- package/scripts/consumer-entries.mjs +209 -0
- package/scripts/lib/contrast.mjs +301 -0
- package/scripts/mcp.mjs +300 -0
- package/scripts/page-lint.mjs +428 -0
- package/scripts/page-reference.mjs +54 -10
- package/dist/badge-locale-Bij94NwL.cjs +0 -1
- package/dist/badge-locale-Du41PpLA.js +0 -533
- package/dist/breadcrumb.context-BssgEydx.js +0 -926
- package/dist/breadcrumb.context-DLsiMS59.cjs +0 -1
- package/dist/components/router/blank-slate.d.ts +0 -21
- package/dist/components/router/blank-slate.d.ts.map +0 -1
- package/dist/components/router/grid.list.d.ts +0 -39
- package/dist/components/router/grid.list.d.ts.map +0 -1
- package/dist/components/router/internal.sidebar.d.ts +0 -61
- package/dist/components/router/internal.sidebar.d.ts.map +0 -1
- package/dist/components/router/nav-main.d.ts +0 -25
- package/dist/components/router/nav-main.d.ts.map +0 -1
- package/dist/components/router/nav-user.d.ts +0 -24
- package/dist/components/router/nav-user.d.ts.map +0 -1
- package/dist/components/router/page-content.d.ts +0 -12
- package/dist/components/router/page-content.d.ts.map +0 -1
- package/dist/components/router/page-header.d.ts +0 -23
- package/dist/components/router/page-header.d.ts.map +0 -1
- package/dist/components/router/page.d.ts +0 -22
- package/dist/components/router/page.d.ts.map +0 -1
- package/dist/components/router/sticky.page.header.d.ts +0 -85
- package/dist/components/router/sticky.page.header.d.ts.map +0 -1
- package/dist/components/router/sub.page.d.ts +0 -50
- package/dist/components/router/sub.page.d.ts.map +0 -1
- package/dist/components/router/sub.page.header.d.ts +0 -37
- package/dist/components/router/sub.page.header.d.ts.map +0 -1
- package/dist/lib/react-markers.d.ts +0 -17
- package/dist/lib/react-markers.d.ts.map +0 -1
- package/dist/loading-provider-B6-R2ONB.cjs +0 -1
- package/dist/user.context-CPmUBBLa.js +0 -522
- package/dist/user.context-xsJgPpcO.cjs +0 -1
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// VDS132 — fail a consumer's lint on the two rules BENTO-AUTHORING calls easy
|
|
3
|
+
// to get wrong, and name the file and line of each.
|
|
4
|
+
//
|
|
5
|
+
// Run it from a product checkout, beside viglet-ds-check-duplicates:
|
|
6
|
+
//
|
|
7
|
+
// viglet-ds-page-lint # scan ./src
|
|
8
|
+
// viglet-ds-page-lint src app # scan these directories
|
|
9
|
+
// viglet-ds-page-lint --json # machine-readable findings
|
|
10
|
+
// viglet-ds-page-lint --warn # report, but exit 0
|
|
11
|
+
// viglet-ds-page-lint --page-pattern <re> # which files are routed pages
|
|
12
|
+
// viglet-ds-page-lint --contrast <css> # measure this stylesheet's tokens (repeatable)
|
|
13
|
+
//
|
|
14
|
+
// The rules:
|
|
15
|
+
//
|
|
16
|
+
// page.column A routed page's outermost element sets a max width, a gutter
|
|
17
|
+
// or a vertical rhythm. BentoShell owns all three and offers the
|
|
18
|
+
// other widths by name, so a page that sets its own disagrees
|
|
19
|
+
// with the next page, and the defect exists only between screens.
|
|
20
|
+
// primary.direct A stylesheet or a style object sets --vg-primary or
|
|
21
|
+
// --vg-primary-foreground. One value there wins on both grounds,
|
|
22
|
+
// so the dark ground takes the light colour; the four
|
|
23
|
+
// --vg-primary-*-base inputs are read per ground.
|
|
24
|
+
// contrast.pair With --contrast: a token pair the product's stylesheet
|
|
25
|
+
// re-keys falls under 4.5:1 on either ground. Measured over the
|
|
26
|
+
// installed preset with the product's stylesheets laid on top,
|
|
27
|
+
// the way they cascade (VDS137).
|
|
28
|
+
// contrast.unread With --contrast: a re-keyed token this cannot read as an
|
|
29
|
+
// opaque colour, reported rather than measured as black.
|
|
30
|
+
//
|
|
31
|
+
// The first two were prose in the vendored skill, and the bins beside this one
|
|
32
|
+
// read exports, imports and vendored files, never a consumer's pages or stylesheets.
|
|
33
|
+
//
|
|
34
|
+
// A page is a file whose name matches `--page-pattern` (default `.page.tsx` or
|
|
35
|
+
// `.page.jsx`), and its outermost element is what its default export returns:
|
|
36
|
+
// each branch of a conditional, and each child of a fragment. A width set deeper
|
|
37
|
+
// inside the page is not this rule's business. A class counts when it is written
|
|
38
|
+
// as a string, in a template, or as a string inside a call such as `cn(...)`.
|
|
39
|
+
//
|
|
40
|
+
// Some pages are deliberately their own, a print view or a kiosk. Keep one by
|
|
41
|
+
// writing, anywhere in the file:
|
|
42
|
+
//
|
|
43
|
+
// // viglet-ds-allow-page-column -- a kiosk with no shell
|
|
44
|
+
// /* viglet-ds-allow-primary -- the theme editor previews a raw value */
|
|
45
|
+
// /* viglet-ds-allow-contrast -- the brand orange, signed off at 4.2:1 as large text */
|
|
46
|
+
//
|
|
47
|
+
// The reason is required. An exemption with none is reported as the finding it
|
|
48
|
+
// was meant to excuse.
|
|
49
|
+
|
|
50
|
+
import { existsSync, readdirSync, readFileSync, statSync } from "node:fs"
|
|
51
|
+
import { createRequire } from "node:module"
|
|
52
|
+
import { dirname, join, relative, resolve } from "node:path"
|
|
53
|
+
import { fileURLToPath } from "node:url"
|
|
54
|
+
|
|
55
|
+
import { AA_TEXT, measurePairs } from "./lib/contrast.mjs"
|
|
56
|
+
|
|
57
|
+
const SOURCE_EXTENSIONS = new Set([".ts", ".tsx", ".js", ".jsx", ".mts", ".mjs", ".cts", ".cjs"])
|
|
58
|
+
const STYLE_EXTENSIONS = new Set([".css", ".scss"])
|
|
59
|
+
const SKIP_DIRS = new Set(["node_modules", ".git", "dist", "build", "out", "coverage", ".next", "storybook-static"])
|
|
60
|
+
|
|
61
|
+
const args = process.argv.slice(2)
|
|
62
|
+
const asJson = args.includes("--json")
|
|
63
|
+
const warnOnly = args.includes("--warn")
|
|
64
|
+
// The value after a flag is not a root. Skipped by index and only where the flag
|
|
65
|
+
// is: VDS78 is what `indexOf(...) + 1` does when it is not.
|
|
66
|
+
const VALUE_FLAGS = new Set(["--page-pattern", "--contrast"])
|
|
67
|
+
const valueAt = new Set(args.flatMap((a, i) => (VALUE_FLAGS.has(a) ? [i + 1] : [])))
|
|
68
|
+
const patternFlag = args.indexOf("--page-pattern")
|
|
69
|
+
const pagePattern = new RegExp(patternFlag === -1 ? String.raw`\.page\.[jt]sx$` : (args[patternFlag + 1] ?? ""))
|
|
70
|
+
const contrastSheets = args.flatMap((a, i) => (a === "--contrast" && args[i + 1] ? [resolve(args[i + 1])] : []))
|
|
71
|
+
const roots = args.filter((a, i) => !a.startsWith("--") && !valueAt.has(i))
|
|
72
|
+
|
|
73
|
+
/** The consumer's TypeScript, or this package's own where it is a checkout. */
|
|
74
|
+
function loadTypeScript() {
|
|
75
|
+
for (const from of [join(process.cwd(), "package.json"), import.meta.url]) {
|
|
76
|
+
try {
|
|
77
|
+
return createRequire(from)("typescript")
|
|
78
|
+
} catch {
|
|
79
|
+
/* try the next */
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
console.error(
|
|
83
|
+
"page-lint: reads pages with the TypeScript compiler, and none is installed here.\n" +
|
|
84
|
+
"Add typescript to this repository's devDependencies and re-run.",
|
|
85
|
+
)
|
|
86
|
+
process.exit(1)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const scanRoots = (roots.length ? roots : ["src"]).map((r) => resolve(r))
|
|
90
|
+
const missing = scanRoots.filter((r) => !existsSync(r) || !statSync(r).isDirectory())
|
|
91
|
+
if (missing.length > 0) {
|
|
92
|
+
console.error(
|
|
93
|
+
`page-lint: not a directory: ${missing.map((r) => relative(process.cwd(), r) || ".").join(", ")}\n` +
|
|
94
|
+
"Pass the source directories explicitly: viglet-ds-page-lint <dir> [dir]",
|
|
95
|
+
)
|
|
96
|
+
process.exit(1)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function collect(dir, files = []) {
|
|
100
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
101
|
+
const full = join(dir, entry.name)
|
|
102
|
+
if (entry.isDirectory()) {
|
|
103
|
+
if (!SKIP_DIRS.has(entry.name) && !entry.name.startsWith(".")) collect(full, files)
|
|
104
|
+
} else {
|
|
105
|
+
files.push(full)
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return files
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const extensionOf = (file) => file.slice(file.lastIndexOf("."))
|
|
112
|
+
const lineOf = (text, index) => text.slice(0, index).split("\n").length
|
|
113
|
+
const shown = (file) => relative(process.cwd(), file).replaceAll("\\", "/")
|
|
114
|
+
|
|
115
|
+
/** Whether a pragma is present, and whether it carries a reason. */
|
|
116
|
+
function pragma(source, name) {
|
|
117
|
+
const found = source.match(new RegExp(String.raw`viglet-ds-allow-${name}\b(.*)`))
|
|
118
|
+
if (!found) return "absent"
|
|
119
|
+
return /^\s*--\s*\S/.test(found[1]) ? "reasoned" : "unreasoned"
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// ---------------------------------------------------------------------------
|
|
123
|
+
// page.column
|
|
124
|
+
|
|
125
|
+
const WIDTH = /^(?:max-w-(?!none$|full$).+|container)$/
|
|
126
|
+
const GUTTER = /^(?:p|px|pl|pr|ps|pe)-(?!0$).+$/
|
|
127
|
+
const RHYTHM = /^(?:py|pt|pb|my|mt|mb)-(?!0$).+$/
|
|
128
|
+
|
|
129
|
+
/** `md:max-w-7xl!` -> `max-w-7xl`: variants and the important marker say where, not what. */
|
|
130
|
+
function utility(token) {
|
|
131
|
+
return token.split(":").pop().replace(/^!/, "").replace(/!$/, "")
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function layoutClasses(classNames) {
|
|
135
|
+
return classNames
|
|
136
|
+
.flatMap((text) => text.split(/\s+/))
|
|
137
|
+
.filter(Boolean)
|
|
138
|
+
.filter((token) => {
|
|
139
|
+
const name = utility(token)
|
|
140
|
+
return WIDTH.test(name) || GUTTER.test(name) || RHYTHM.test(name)
|
|
141
|
+
})
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function pageFindings(ts, file, source) {
|
|
145
|
+
const sf = ts.createSourceFile(file, source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX)
|
|
146
|
+
|
|
147
|
+
/** Every string a className expression can produce, conditions and calls included. */
|
|
148
|
+
function strings(node, found = []) {
|
|
149
|
+
if (!node) return found
|
|
150
|
+
if (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) {
|
|
151
|
+
found.push(node.text)
|
|
152
|
+
} else if (ts.isTemplateExpression(node)) {
|
|
153
|
+
found.push(node.head.text, ...node.templateSpans.map((span) => span.literal.text))
|
|
154
|
+
for (const span of node.templateSpans) strings(span.expression, found)
|
|
155
|
+
} else {
|
|
156
|
+
// forEachChild stops at the first callback that returns a value, so this
|
|
157
|
+
// one returns nothing: `cn("grid", wide && "max-w-6xl")` has two strings.
|
|
158
|
+
ts.forEachChild(node, (child) => {
|
|
159
|
+
strings(child, found)
|
|
160
|
+
})
|
|
161
|
+
}
|
|
162
|
+
return found
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function classNameOf(opening) {
|
|
166
|
+
for (const attribute of opening.attributes.properties) {
|
|
167
|
+
if (!ts.isJsxAttribute(attribute) || attribute.name.getText(sf) !== "className") continue
|
|
168
|
+
return strings(attribute.initializer)
|
|
169
|
+
}
|
|
170
|
+
return []
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/** The outermost elements an expression renders. */
|
|
174
|
+
function outermost(node, found = []) {
|
|
175
|
+
if (!node) return found
|
|
176
|
+
if (ts.isParenthesizedExpression(node)) return outermost(node.expression, found)
|
|
177
|
+
if (ts.isConditionalExpression(node)) {
|
|
178
|
+
outermost(node.whenTrue, found)
|
|
179
|
+
return outermost(node.whenFalse, found)
|
|
180
|
+
}
|
|
181
|
+
if (ts.isBinaryExpression(node)) return outermost(node.right, found)
|
|
182
|
+
if (ts.isJsxElement(node)) found.push(node.openingElement)
|
|
183
|
+
else if (ts.isJsxSelfClosingElement(node)) found.push(node)
|
|
184
|
+
else if (ts.isJsxFragment(node)) {
|
|
185
|
+
for (const child of node.children) outermost(child, found)
|
|
186
|
+
}
|
|
187
|
+
return found
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/** What a function returns, without descending into the functions it declares. */
|
|
191
|
+
function returned(fn) {
|
|
192
|
+
if (!fn.body) return []
|
|
193
|
+
if (!ts.isBlock(fn.body)) return [fn.body]
|
|
194
|
+
const found = []
|
|
195
|
+
const visit = (node) => {
|
|
196
|
+
if (ts.isFunctionLike(node)) return
|
|
197
|
+
if (ts.isReturnStatement(node) && node.expression) found.push(node.expression)
|
|
198
|
+
ts.forEachChild(node, visit)
|
|
199
|
+
}
|
|
200
|
+
ts.forEachChild(fn.body, visit)
|
|
201
|
+
return found
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/** A function, through `memo(...)`, `forwardRef(...)` or an identifier declared here. */
|
|
205
|
+
function asFunction(node) {
|
|
206
|
+
if (!node) return null
|
|
207
|
+
if (ts.isFunctionDeclaration(node) || ts.isFunctionExpression(node) || ts.isArrowFunction(node)) return node
|
|
208
|
+
if (ts.isParenthesizedExpression(node)) return asFunction(node.expression)
|
|
209
|
+
if (ts.isCallExpression(node)) return asFunction(node.arguments[0])
|
|
210
|
+
if (ts.isIdentifier(node)) {
|
|
211
|
+
for (const statement of sf.statements) {
|
|
212
|
+
if (ts.isFunctionDeclaration(statement) && statement.name?.text === node.text) return statement
|
|
213
|
+
if (ts.isVariableStatement(statement)) {
|
|
214
|
+
for (const declaration of statement.declarationList.declarations) {
|
|
215
|
+
if (ts.isIdentifier(declaration.name) && declaration.name.text === node.text) {
|
|
216
|
+
return asFunction(declaration.initializer)
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
return null
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
let page = null
|
|
226
|
+
for (const statement of sf.statements) {
|
|
227
|
+
if (ts.isExportAssignment(statement)) page = asFunction(statement.expression)
|
|
228
|
+
const modifiers = ts.canHaveModifiers(statement) ? (ts.getModifiers(statement) ?? []) : []
|
|
229
|
+
if (
|
|
230
|
+
ts.isFunctionDeclaration(statement) &&
|
|
231
|
+
modifiers.some((m) => m.kind === ts.SyntaxKind.ExportKeyword) &&
|
|
232
|
+
modifiers.some((m) => m.kind === ts.SyntaxKind.DefaultKeyword)
|
|
233
|
+
) {
|
|
234
|
+
page = statement
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
if (!page) return []
|
|
238
|
+
|
|
239
|
+
const findings = []
|
|
240
|
+
for (const expression of returned(page)) {
|
|
241
|
+
for (const opening of outermost(expression)) {
|
|
242
|
+
const offending = layoutClasses(classNameOf(opening))
|
|
243
|
+
if (offending.length === 0) continue
|
|
244
|
+
findings.push({
|
|
245
|
+
file: shown(file),
|
|
246
|
+
line: sf.getLineAndCharacterOfPosition(opening.getStart(sf)).line + 1,
|
|
247
|
+
rule: "page.column",
|
|
248
|
+
detail: `the page's outermost element sets ${[...new Set(offending)].join(" ")}`,
|
|
249
|
+
fix: 'remove them: BentoShell sets the column, and column="narrow" or "wide" names the other widths',
|
|
250
|
+
})
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
return findings
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// ---------------------------------------------------------------------------
|
|
257
|
+
// primary.direct
|
|
258
|
+
|
|
259
|
+
// A declaration or a write, never a read: `var(--vg-primary)` has no colon after
|
|
260
|
+
// the name, `--vg-primary-base:` has more name before it, and
|
|
261
|
+
// `getPropertyValue("--vg-primary")` closes a call where `setProperty` takes a
|
|
262
|
+
// second argument.
|
|
263
|
+
const DECLARED = /--vg-primary(?:-foreground)?\s*:/g
|
|
264
|
+
const KEYED = /["'`]--vg-primary(?:-foreground)?["'`]\s*[:,]/g
|
|
265
|
+
|
|
266
|
+
// Blanked rather than removed, so a finding's line survives. In a script only a
|
|
267
|
+
// comment that opens its line: `//` also sits inside a URL, and a glob such as
|
|
268
|
+
// "src/**" opens a block anywhere else.
|
|
269
|
+
const blank = (text) => text.replace(/[^\n]/g, " ")
|
|
270
|
+
const withoutComments = (source, isStyle) =>
|
|
271
|
+
isStyle
|
|
272
|
+
? source.replace(/\/\*[\s\S]*?\*\//g, blank)
|
|
273
|
+
: source.replace(/^[ \t]*\/\*[\s\S]*?\*\//gm, blank).replace(/^[ \t]*\/\/.*$/gm, blank)
|
|
274
|
+
|
|
275
|
+
function primaryFindings(file, source, isStyle) {
|
|
276
|
+
const text = withoutComments(source, isStyle)
|
|
277
|
+
const findings = []
|
|
278
|
+
const seen = new Set()
|
|
279
|
+
for (const pattern of isStyle ? [DECLARED] : [DECLARED, KEYED]) {
|
|
280
|
+
for (const match of text.matchAll(pattern)) {
|
|
281
|
+
const line = lineOf(text, match.index)
|
|
282
|
+
const name = match[0].replace(/["'`:,\s]/g, "")
|
|
283
|
+
if (seen.has(`${line}:${name}`)) continue
|
|
284
|
+
seen.add(`${line}:${name}`)
|
|
285
|
+
findings.push({
|
|
286
|
+
file: shown(file),
|
|
287
|
+
line,
|
|
288
|
+
rule: "primary.direct",
|
|
289
|
+
detail: `sets ${name}`,
|
|
290
|
+
fix: "claim it through the --vg-primary-base and --vg-primary-foreground-base inputs, light and -dark, at :root",
|
|
291
|
+
})
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
return findings.sort((a, b) => a.line - b.line)
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// ---------------------------------------------------------------------------
|
|
298
|
+
|
|
299
|
+
let ts = null
|
|
300
|
+
const findings = []
|
|
301
|
+
let scanned = 0
|
|
302
|
+
let pages = 0
|
|
303
|
+
|
|
304
|
+
for (const root of scanRoots) {
|
|
305
|
+
for (const file of collect(root)) {
|
|
306
|
+
const extension = extensionOf(file)
|
|
307
|
+
const isStyle = STYLE_EXTENSIONS.has(extension)
|
|
308
|
+
const isSource = SOURCE_EXTENSIONS.has(extension)
|
|
309
|
+
if (!isStyle && !isSource) continue
|
|
310
|
+
if (/\.(test|spec|stories)\./.test(file)) continue
|
|
311
|
+
|
|
312
|
+
const source = readFileSync(file, "utf8")
|
|
313
|
+
scanned++
|
|
314
|
+
|
|
315
|
+
const fileFindings = []
|
|
316
|
+
if (isSource && pagePattern.test(file.replaceAll("\\", "/"))) {
|
|
317
|
+
pages++
|
|
318
|
+
ts ??= loadTypeScript()
|
|
319
|
+
fileFindings.push(...pageFindings(ts, file, source))
|
|
320
|
+
}
|
|
321
|
+
fileFindings.push(...primaryFindings(file, source, isStyle))
|
|
322
|
+
|
|
323
|
+
const allowed = {
|
|
324
|
+
"page.column": pragma(source, "page-column"),
|
|
325
|
+
"primary.direct": pragma(source, "primary"),
|
|
326
|
+
}
|
|
327
|
+
for (const finding of fileFindings) {
|
|
328
|
+
const state = allowed[finding.rule]
|
|
329
|
+
if (state === "reasoned") continue
|
|
330
|
+
if (state === "unreasoned") finding.detail += " (an exemption here gives no reason, so it does not apply)"
|
|
331
|
+
findings.push(finding)
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
if (scanned === 0) {
|
|
337
|
+
console.error(
|
|
338
|
+
`page-lint: no source file under ${scanRoots.map((r) => shown(r) || ".").join(", ")}, so this would pass vacuously.`,
|
|
339
|
+
)
|
|
340
|
+
process.exit(1)
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// ---------------------------------------------------------------------------
|
|
344
|
+
// contrast.pair and contrast.unread
|
|
345
|
+
|
|
346
|
+
/** The preset this package ships, or its source where this is a checkout before a build. */
|
|
347
|
+
function presetCss() {
|
|
348
|
+
const here = dirname(fileURLToPath(import.meta.url))
|
|
349
|
+
for (const candidate of [join(here, "..", "dist", "preset.css"), join(here, "..", "src", "styles", "preset.css")]) {
|
|
350
|
+
if (existsSync(candidate)) return readFileSync(candidate, "utf8")
|
|
351
|
+
}
|
|
352
|
+
console.error("page-lint: --contrast needs the preset, and this copy of the package has none.")
|
|
353
|
+
process.exit(1)
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Every pair a product's stylesheet re-keys, measured on both grounds. A pair
|
|
358
|
+
* the product does not touch is the preset's, and the package's own gate holds
|
|
359
|
+
* it, so it is not reported here.
|
|
360
|
+
*/
|
|
361
|
+
function contrastFindings() {
|
|
362
|
+
const absent = contrastSheets.filter((file) => !existsSync(file))
|
|
363
|
+
if (absent.length > 0) {
|
|
364
|
+
console.error(`page-lint: --contrast names a stylesheet that is not there: ${absent.map(shown).join(", ")}`)
|
|
365
|
+
process.exit(1)
|
|
366
|
+
}
|
|
367
|
+
const products = contrastSheets.map((file) => ({ name: shown(file), css: readFileSync(file, "utf8") }))
|
|
368
|
+
const sheets = [{ name: "preset", css: presetCss() }, ...products]
|
|
369
|
+
|
|
370
|
+
const byPair = new Map()
|
|
371
|
+
for (const measured of [...measurePairs(sheets, "light"), ...measurePairs(sheets, "dark")]) {
|
|
372
|
+
const key = `${measured.foreground} on ${measured.surface}`
|
|
373
|
+
byPair.set(key, { ...byPair.get(key), [measured.ground]: measured })
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
const out = []
|
|
377
|
+
for (const [pair, grounds] of byPair) {
|
|
378
|
+
const both = [grounds.light, grounds.dark].filter(Boolean)
|
|
379
|
+
const touched = both.flatMap((m) => m.declared).find((d) => d.sheet !== "preset")
|
|
380
|
+
if (!touched) continue
|
|
381
|
+
|
|
382
|
+
const unread = [...new Set(both.flatMap((m) => m.unread))]
|
|
383
|
+
const failing = both.some((m) => m.ratio !== null && m.ratio < AA_TEXT)
|
|
384
|
+
if (unread.length === 0 && !failing) continue
|
|
385
|
+
|
|
386
|
+
const product = products.find((p) => p.name === touched.sheet)
|
|
387
|
+
const exemption = pragma(product.css, "contrast")
|
|
388
|
+
if (exemption === "reasoned") continue
|
|
389
|
+
|
|
390
|
+
const at = product.css.search(new RegExp(String.raw`${touched.token}\s*:`))
|
|
391
|
+
// Only a token with a -dark twin can be stepped on one ground alone.
|
|
392
|
+
const twin = sheets.some((sheet) => sheet.css.includes(`${touched.token}-dark:`))
|
|
393
|
+
const said = both
|
|
394
|
+
.map((m) => (m.ratio === null ? `unread on the ${m.ground} ground` : `${m.ratio.toFixed(2)}:1 on the ${m.ground} ground`))
|
|
395
|
+
.join(" and ")
|
|
396
|
+
out.push({
|
|
397
|
+
file: product.name,
|
|
398
|
+
line: at === -1 ? 1 : lineOf(product.css, at),
|
|
399
|
+
rule: unread.length > 0 ? "contrast.unread" : "contrast.pair",
|
|
400
|
+
detail:
|
|
401
|
+
`${pair} is ${said}; ${AA_TEXT}:1 needed` +
|
|
402
|
+
(exemption === "unreasoned" ? " (an exemption here gives no reason, so it does not apply)" : ""),
|
|
403
|
+
fix:
|
|
404
|
+
unread.length > 0
|
|
405
|
+
? `write ${unread.join(" and ")} as an oklch(), hex, rgb() or hsl() colour, or a var() or color-mix(in oklab) this can follow`
|
|
406
|
+
: `step ${touched.token} until the pair clears ${AA_TEXT}:1 on both grounds` +
|
|
407
|
+
(twin ? `; ${touched.token}-dark sets the dark ground on its own` : ""),
|
|
408
|
+
})
|
|
409
|
+
}
|
|
410
|
+
return out
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
if (contrastSheets.length > 0) findings.push(...contrastFindings())
|
|
414
|
+
|
|
415
|
+
if (asJson) {
|
|
416
|
+
console.log(JSON.stringify({ scanned, pages, findings }, null, 2))
|
|
417
|
+
} else if (findings.length === 0) {
|
|
418
|
+
const measuredToo = contrastSheets.length > 0 ? `, every pair ${contrastSheets.length} stylesheet(s) re-key clears ${AA_TEXT}:1` : ""
|
|
419
|
+
console.log(`page-lint: ${scanned} file(s) scanned, ${pages} of them pages — no page sets its own column, nothing sets --vg-primary${measuredToo}.`)
|
|
420
|
+
} else {
|
|
421
|
+
console.error(`\npage-lint: ${findings.length} finding(s)\n`)
|
|
422
|
+
for (const finding of findings) {
|
|
423
|
+
console.error(` ${finding.file}:${finding.line} ${finding.rule} ${finding.detail}`)
|
|
424
|
+
console.error(` ${finding.fix}\n`)
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
process.exit(findings.length > 0 && !warnOnly ? 1 : 0)
|
|
@@ -102,10 +102,14 @@ An artboard opens in a browser straight from the file tree.
|
|
|
102
102
|
- A product claims \`--primary\` through the four \`--vg-primary-*-base\` inputs at \`:root\`,
|
|
103
103
|
never by setting \`--vg-primary\` itself, which would key the dark ground to the light value.
|
|
104
104
|
|
|
105
|
+
\`viglet-ds-page-lint <dir>\` fails on either one, naming the file and line. Point it at the
|
|
106
|
+
directories whose pages render inside \`BentoShell\`.
|
|
107
|
+
|
|
105
108
|
## Checking it is current
|
|
106
109
|
|
|
107
110
|
\`\`\`bash
|
|
108
111
|
viglet-ds-page-reference --check
|
|
112
|
+
viglet-ds-page-lint src
|
|
109
113
|
\`\`\`
|
|
110
114
|
`
|
|
111
115
|
}
|
|
@@ -183,10 +187,42 @@ function declaration() {
|
|
|
183
187
|
}
|
|
184
188
|
}
|
|
185
189
|
|
|
190
|
+
/**
|
|
191
|
+
* VDS135 — whether this repository enables the `viglet-ds` Claude Code plugin.
|
|
192
|
+
*
|
|
193
|
+
* The plugin delivers the skill into every session by name and updates with it,
|
|
194
|
+
* so a vendored copy beside it is a second skill of the same name that drifts.
|
|
195
|
+
* The artboards are different: a consumer wants them on disk, and they stay.
|
|
196
|
+
* Read from the project's settings, where enabling a plugin for a repository is
|
|
197
|
+
* recorded, and never guessed from what is installed on this machine.
|
|
198
|
+
*/
|
|
199
|
+
function pluginEnabled() {
|
|
200
|
+
for (const name of [".claude/settings.json", ".claude/settings.local.json"]) {
|
|
201
|
+
const at = join(root, name)
|
|
202
|
+
if (!existsSync(at)) continue
|
|
203
|
+
try {
|
|
204
|
+
const enabled = JSON.parse(readFileSync(at, "utf8")).enabledPlugins ?? {}
|
|
205
|
+
if (Object.entries(enabled).some(([id, on]) => on === true && id.split("@")[0] === "viglet-ds")) {
|
|
206
|
+
return true
|
|
207
|
+
}
|
|
208
|
+
} catch {
|
|
209
|
+
/* a settings file this cannot read enables nothing */
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
return false
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const plugin = pluginEnabled()
|
|
216
|
+
const SKILL_FILES = [SKILL, `${SKILL_DIR}/authoring.md`, `${SKILL_DIR}/boundary.md`]
|
|
217
|
+
|
|
186
218
|
const surfaces = [
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
219
|
+
...(plugin
|
|
220
|
+
? []
|
|
221
|
+
: [
|
|
222
|
+
copied(SKILL, orientation(canvasDir, artboards.length)),
|
|
223
|
+
copied(`${SKILL_DIR}/authoring.md`, readFileSync(join(payload, "docs", "BENTO-AUTHORING.md"), "utf8")),
|
|
224
|
+
copied(`${SKILL_DIR}/boundary.md`, readFileSync(join(payload, "docs", "BENTO-BOUNDARY.md"), "utf8")),
|
|
225
|
+
]),
|
|
190
226
|
...artboards.map((name) =>
|
|
191
227
|
copied(`${canvasDir}/vds-${name}`, readFileSync(join(REFERENCE, name), "utf8")),
|
|
192
228
|
),
|
|
@@ -200,11 +236,13 @@ const surfaces = [
|
|
|
200
236
|
* "refresh" means downgrade and every word of a drift report would be wrong. So
|
|
201
237
|
* it is named and refused instead.
|
|
202
238
|
*/
|
|
203
|
-
const wired = existsSync(join(root, SKILL))
|
|
204
|
-
const stamped =
|
|
239
|
+
const wired = plugin || existsSync(join(root, SKILL))
|
|
240
|
+
const stamped = existsSync(join(root, SKILL))
|
|
205
241
|
? (/^vds-version:\s*(\S+)\s*$/m.exec(readFileSync(join(root, SKILL), "utf8"))?.[1] ?? null)
|
|
206
242
|
: null
|
|
207
243
|
const ahead =
|
|
244
|
+
// With the plugin on, the vendored skill is on its way out, so its stamp says nothing.
|
|
245
|
+
!plugin &&
|
|
208
246
|
stamped !== null &&
|
|
209
247
|
stamped !== version &&
|
|
210
248
|
stamped.localeCompare(version, undefined, { numeric: true }) > 0
|
|
@@ -220,11 +258,16 @@ const changing = surfaces.filter((s) => s.drifted)
|
|
|
220
258
|
* gate to mean what it says.
|
|
221
259
|
*/
|
|
222
260
|
const shipped = new Set(artboards.map((name) => `vds-${name}`))
|
|
223
|
-
const orphans =
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
261
|
+
const orphans = [
|
|
262
|
+
...(existsSync(join(root, canvasDir))
|
|
263
|
+
? readdirSync(join(root, canvasDir))
|
|
264
|
+
.filter((name) => name.startsWith("vds-") && name.endsWith(".dc.html") && !shipped.has(name))
|
|
265
|
+
.map((name) => `${canvasDir}/${name}`)
|
|
266
|
+
: []),
|
|
267
|
+
// A vendored skill left behind once the plugin carries it. Only one this
|
|
268
|
+
// package stamped: a skill of the same name the repository wrote is its own.
|
|
269
|
+
...(plugin && stamped !== null ? SKILL_FILES.filter((file) => existsSync(join(root, file))) : []),
|
|
270
|
+
]
|
|
228
271
|
|
|
229
272
|
/** created / updated, in the conditional under `--check` and the past tense after a write. */
|
|
230
273
|
function state(surface) {
|
|
@@ -246,6 +289,7 @@ if (asJson) {
|
|
|
246
289
|
root,
|
|
247
290
|
canvasDir,
|
|
248
291
|
wired,
|
|
292
|
+
plugin,
|
|
249
293
|
stamped,
|
|
250
294
|
ahead,
|
|
251
295
|
code: code(),
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
const e=require("./rolldown-runtime-BocRIvOZ.cjs"),t=require("./utils-Oagwe_oa.cjs");let n=require("react");n=e.t(n,1);let r=require("react/jsx-runtime"),i=require("@radix-ui/react-slot"),a=require("class-variance-authority"),o=require("react-i18next"),s=require("@radix-ui/react-dialog");s=e.t(s,1);let c=require("@radix-ui/react-dropdown-menu");c=e.t(c,1);let l=require("@radix-ui/react-tooltip");l=e.t(l,1);var u=(...e)=>e.filter((e,t,n)=>!!e&&e.trim()!==``&&n.indexOf(e)===t).join(` `).trim(),d=e=>e.replace(/([a-z0-9])([A-Z])/g,`$1-$2`).toLowerCase(),f=e=>e.replace(/^([A-Z])|[\s-_]+(\w)/g,(e,t,n)=>n?n.toUpperCase():t.toLowerCase()),p=e=>{let t=f(e);return t.charAt(0).toUpperCase()+t.slice(1)},m={xmlns:`http://www.w3.org/2000/svg`,width:24,height:24,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:2,strokeLinecap:`round`,strokeLinejoin:`round`},h=e=>{for(let t in e)if(t.startsWith(`aria-`)||t===`role`||t===`title`)return!0;return!1},g=(0,n.createContext)({}),_=()=>(0,n.useContext)(g),v=(0,n.forwardRef)(({color:e,size:t,strokeWidth:r,absoluteStrokeWidth:i,className:a=``,children:o,iconNode:s,...c},l)=>{let{size:d=24,strokeWidth:f=2,absoluteStrokeWidth:p=!1,color:g=`currentColor`,className:v=``}=_()??{},y=i??p?Number(r??f)*24/Number(t??d):r??f;return(0,n.createElement)(`svg`,{ref:l,...m,width:t??d??m.width,height:t??d??m.height,stroke:e??g,strokeWidth:y,className:u(`lucide`,v,a),...!o&&!h(c)&&{"aria-hidden":`true`},...c},[...s.map(([e,t])=>(0,n.createElement)(e,t)),...Array.isArray(o)?o:[o]])}),y=(e,t)=>{let r=(0,n.forwardRef)(({className:r,...i},a)=>(0,n.createElement)(v,{ref:a,iconNode:t,className:u(`lucide-${d(p(e))}`,`lucide-${e}`,r),...i}));return r.displayName=p(e),r},b=y(`check`,[[`path`,{d:`M20 6 9 17l-5-5`,key:`1gmf2c`}]]),x=y(`chevron-right`,[[`path`,{d:`m9 18 6-6-6-6`,key:`mthhwq`}]]),ee=y(`circle`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}]]),S=y(`globe`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20`,key:`13o1zl`}],[`path`,{d:`M2 12h20`,key:`9i4pu4`}]]),C=y(`x`,[[`path`,{d:`M18 6 6 18`,key:`1bl5f8`}],[`path`,{d:`m6 6 12 12`,key:`d8bk6v`}]]),w=(0,a.cva)(`inline-flex items-center justify-center rounded-full border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden`,{variants:{variant:{default:`border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90`,secondary:`border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90`,destructive:`border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60`,outline:`text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground`}},defaultVariants:{variant:`default`}});function T({className:e,variant:n,asChild:a=!1,...o}){return(0,r.jsx)(a?i.Slot:`span`,{"data-slot":`badge`,className:t.t(w({variant:n}),e),...o})}function te({...e}){return(0,r.jsx)(s.Root,{"data-slot":`dialog`,...e})}function ne({...e}){return(0,r.jsx)(s.Trigger,{"data-slot":`dialog-trigger`,...e})}function E({...e}){return(0,r.jsx)(s.Portal,{"data-slot":`dialog-portal`,...e})}function D({...e}){return(0,r.jsx)(s.Close,{"data-slot":`dialog-close`,...e})}function O({className:e,...n}){return(0,r.jsx)(s.Overlay,{"data-slot":`dialog-overlay`,className:t.t(`data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50`,e),...n})}function k({className:e,children:n,showCloseButton:i=!0,...a}){let{t:c}=(0,o.useTranslation)();return(0,r.jsxs)(E,{"data-slot":`dialog-portal`,children:[(0,r.jsx)(O,{}),(0,r.jsxs)(s.Content,{"data-slot":`dialog-content`,className:t.t(`bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg`,e),...a,children:[n,i&&(0,r.jsxs)(s.Close,{"data-slot":`dialog-close`,className:`ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4`,children:[(0,r.jsx)(C,{}),(0,r.jsx)(`span`,{className:`sr-only`,children:c(`dialog.close`,{defaultValue:`Close`})})]})]})]})}function A({className:e,...n}){return(0,r.jsx)(`div`,{"data-slot":`dialog-header`,className:t.t(`flex flex-col gap-2 text-center sm:text-left`,e),...n})}function j({className:e,...n}){return(0,r.jsx)(`div`,{"data-slot":`dialog-footer`,className:t.t(`flex flex-col-reverse gap-2 sm:flex-row sm:justify-end`,e),...n})}function M({className:e,...n}){return(0,r.jsx)(s.Title,{"data-slot":`dialog-title`,className:t.t(`text-lg leading-none font-semibold`,e),...n})}function N({className:e,...n}){return(0,r.jsx)(s.Description,{"data-slot":`dialog-description`,className:t.t(`text-muted-foreground text-sm`,e),...n})}function P({...e}){return(0,r.jsx)(c.Root,{"data-slot":`dropdown-menu`,...e})}function F({...e}){return(0,r.jsx)(c.Portal,{"data-slot":`dropdown-menu-portal`,...e})}function I({...e}){return(0,r.jsx)(c.Trigger,{"data-slot":`dropdown-menu-trigger`,...e})}function L({className:e,sideOffset:n=4,...i}){return(0,r.jsx)(c.Portal,{children:(0,r.jsx)(c.Content,{"data-slot":`dropdown-menu-content`,sideOffset:n,className:t.t(`bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md`,e),...i})})}function R({...e}){return(0,r.jsx)(c.Group,{"data-slot":`dropdown-menu-group`,...e})}function z({className:e,inset:n,variant:i=`default`,...a}){return(0,r.jsx)(c.Item,{"data-slot":`dropdown-menu-item`,"data-inset":n,"data-variant":i,className:t.t(`focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4`,e),...a})}function B({className:e,children:n,checked:i,...a}){return(0,r.jsxs)(c.CheckboxItem,{"data-slot":`dropdown-menu-checkbox-item`,className:t.t(`focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4`,e),checked:i,...a,children:[(0,r.jsx)(`span`,{className:`pointer-events-none absolute left-2 flex size-3.5 items-center justify-center`,children:(0,r.jsx)(c.ItemIndicator,{children:(0,r.jsx)(b,{className:`size-4`})})}),n]})}function V({...e}){return(0,r.jsx)(c.RadioGroup,{"data-slot":`dropdown-menu-radio-group`,...e})}function H({className:e,children:n,...i}){return(0,r.jsxs)(c.RadioItem,{"data-slot":`dropdown-menu-radio-item`,className:t.t(`focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4`,e),...i,children:[(0,r.jsx)(`span`,{className:`pointer-events-none absolute left-2 flex size-3.5 items-center justify-center`,children:(0,r.jsx)(c.ItemIndicator,{children:(0,r.jsx)(ee,{className:`size-2 fill-current`})})}),n]})}function re({className:e,inset:n,...i}){return(0,r.jsx)(c.Label,{"data-slot":`dropdown-menu-label`,"data-inset":n,className:t.t(`px-2 py-1.5 text-sm font-medium data-[inset]:pl-8`,e),...i})}function U({className:e,...n}){return(0,r.jsx)(c.Separator,{"data-slot":`dropdown-menu-separator`,className:t.t(`bg-border -mx-1 my-1 h-px`,e),...n})}function W({className:e,...n}){return(0,r.jsx)(`span`,{"data-slot":`dropdown-menu-shortcut`,className:t.t(`text-muted-foreground ml-auto text-xs tracking-widest`,e),...n})}function G({...e}){return(0,r.jsx)(c.Sub,{"data-slot":`dropdown-menu-sub`,...e})}function K({className:e,inset:n,children:i,...a}){return(0,r.jsxs)(c.SubTrigger,{"data-slot":`dropdown-menu-sub-trigger`,"data-inset":n,className:t.t(`focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4`,e),...a,children:[i,(0,r.jsx)(x,{className:`ml-auto size-4`})]})}function q({className:e,...n}){return(0,r.jsx)(c.SubContent,{"data-slot":`dropdown-menu-sub-content`,className:t.t(`bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden rounded-md border p-1 shadow-lg`,e),...n})}var J=(0,a.cva)(`inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all duration-200 cursor-pointer disabled:cursor-not-allowed disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:ring-[3px]`,{variants:{variant:{default:[`bg-gradient-to-r from-[var(--vg-accent-fill-from)] to-[var(--vg-accent-fill-to)] text-white`,`shadow-md shadow-[var(--vg-accent-shadow)]`,`hover:from-[var(--vg-accent-fill-from-hover)] hover:to-[var(--vg-accent-fill-to-hover)]`,`hover:shadow-lg hover:shadow-[var(--vg-accent-shadow-hover)]`,`focus-visible:ring-[var(--vg-accent-ring)]`].join(` `),secondary:[`bg-gradient-to-r from-slate-600 to-slate-700 text-white`,`shadow-md shadow-slate-500/25`,`hover:from-slate-700 hover:to-slate-800`,`hover:shadow-lg hover:shadow-slate-500/30`,`focus-visible:ring-slate-500/50`,`dark:from-slate-500 dark:to-slate-600`,`dark:shadow-slate-500/20`,`dark:hover:from-slate-600 dark:hover:to-slate-700`,`dark:hover:shadow-slate-500/25`,`dark:focus-visible:ring-slate-400/50`].join(` `),destructive:[`bg-gradient-to-r from-red-600 to-rose-600 text-white`,`shadow-md shadow-red-500/25`,`hover:from-red-700 hover:to-rose-700`,`hover:shadow-lg hover:shadow-red-500/30`,`focus-visible:ring-red-500/50`,`dark:from-red-500 dark:to-rose-500`,`dark:shadow-red-500/20`,`dark:hover:from-red-600 dark:hover:to-rose-600`,`dark:hover:shadow-red-500/25`,`dark:focus-visible:ring-red-400/50`].join(` `),success:[`bg-gradient-to-r from-emerald-600 to-teal-600 text-white`,`shadow-md shadow-emerald-500/25`,`hover:from-emerald-700 hover:to-teal-700`,`hover:shadow-lg hover:shadow-emerald-500/30`,`focus-visible:ring-emerald-500/50`,`dark:from-emerald-500 dark:to-teal-500`,`dark:shadow-emerald-500/20`,`dark:hover:from-emerald-600 dark:hover:to-teal-600`,`dark:hover:shadow-emerald-500/25`,`dark:focus-visible:ring-emerald-400/50`].join(` `),outline:[`border-2 border-[var(--vg-accent-fg)] text-[var(--vg-accent-fg)] bg-transparent`,`hover:bg-[var(--vg-accent-fill-from)] hover:text-white`,`shadow-sm hover:shadow-md hover:shadow-[var(--vg-accent-shadow)]`,`focus-visible:ring-[var(--vg-accent-ring)]`].join(` `),ghost:[`bg-transparent text-[var(--vg-accent-fg)]`,`hover:bg-[var(--vg-accent-surface)]`,`focus-visible:ring-[var(--vg-accent-ring)]`].join(` `)},size:{default:`h-11 px-5 py-2 has-[>svg]:px-4`,sm:`h-9 rounded-md gap-1.5 px-4 has-[>svg]:px-3 text-xs`,lg:`h-12 rounded-md px-8 has-[>svg]:px-6 text-base`,icon:`size-11`,"icon-sm":`size-9`,"icon-lg":`size-12`}},defaultVariants:{variant:`default`,size:`default`}});function Y({className:e,variant:n,size:a,asChild:o=!1,loading:s=!1,...c}){let l=t.t(J({variant:n,size:a,className:e}));return(0,r.jsx)(o?i.Slot:`button`,{"data-slot":`gradient-button`,className:l,disabled:s||c.disabled,...c,children:s?(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(`svg`,{className:`size-4 animate-spin`,xmlns:`http://www.w3.org/2000/svg`,fill:`none`,viewBox:`0 0 24 24`,children:[(0,r.jsx)(`circle`,{className:`opacity-25`,cx:`12`,cy:`12`,r:`10`,stroke:`currentColor`,strokeWidth:`4`}),(0,r.jsx)(`path`,{className:`opacity-75`,fill:`currentColor`,d:`M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z`})]}),c.children]}):c.children})}function X({className:e,type:n,...i}){return(0,r.jsx)(`input`,{type:n,"data-slot":`input`,className:t.t(`file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input h-9 w-full min-w-0 rounded-md border bg-transparent pl-3 pr-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm`,`focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]`,`aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive`,e),...i})}function ie({className:e,...n}){return(0,r.jsx)(`div`,{"data-slot":`skeleton`,className:t.t(`bg-accent animate-pulse rounded-md`,e),...n})}function Z({delayDuration:e=0,...t}){return(0,r.jsx)(l.Provider,{"data-slot":`tooltip-provider`,delayDuration:e,...t})}function ae({...e}){return(0,r.jsx)(Z,{children:(0,r.jsx)(l.Root,{"data-slot":`tooltip`,...e})})}function oe({...e}){return(0,r.jsx)(l.Trigger,{"data-slot":`tooltip-trigger`,...e})}function se({className:e,sideOffset:n=0,children:i,...a}){return(0,r.jsx)(l.Portal,{children:(0,r.jsxs)(l.Content,{"data-slot":`tooltip-content`,sideOffset:n,className:t.t(`bg-foreground text-background animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance`,e),...a,children:[i,(0,r.jsx)(l.Arrow,{className:`bg-foreground fill-foreground z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]`})]})})}var ce=({text:e,href:n,onClick:i,className:a,prefix:o})=>{if(!e)return null;let s=t.r(e);return(0,r.jsxs)(T,{variant:`outline`,title:e,onClick:()=>n&&i?.(n),className:t.t(`vg-badge-colorful text-xs font-medium px-2 py-0.5 gap-1.5 cursor-pointer transition-all hover:opacity-80`,`dynamic-badge-${e.length}`,a),style:{"--badge-bg":s.light.bg,"--badge-text":s.light.text,"--badge-border":s.light.border,"--badge-dark-bg":s.dark.bg,"--badge-dark-text":s.dark.text,"--badge-dark-border":s.dark.border},children:[o,(0,r.jsx)(`span`,{children:e})]})},le={AR:`SA`,BN:`BD`,CA:`ES`,CS:`CZ`,DA:`DK`,DE:`DE`,EL:`GR`,EN:`US`,EU:`ES`,FA:`IR`,FI:`FI`,FIL:`PH`,FR:`FR`,GA:`IE`,GL:`ES`,GU:`IN`,HE:`IL`,HI:`IN`,HU:`HU`,ID:`ID`,IT:`IT`,JA:`JP`,KN:`IN`,KO:`KR`,MR:`IN`,MSA:`MY`,NL:`NL`,NO:`NO`,PL:`PL`,PT:`BR`,RO:`RO`,RU:`RU`,ES:`ES`,SV:`SE`,TA:`IN`,TH:`TH`,TR:`TR`,UK:`UA`,UR:`PK`,VI:`VN`,ZH:`CN`},Q={UK:`GB`};function $(e){if(!e)return``;let{language:n,region:r}=t.i(e);if(r)return(Q[r]||r).toLowerCase();let i=le[n];return i?i.toLowerCase():(Q[n]||n).toLowerCase()}var ue=({locale:e,className:i})=>{let a=$(e),[o,s]=(0,n.useState)(null),c=o===a;return(0,r.jsxs)(T,{variant:`secondary`,className:t.t(`font-mono gap-2 py-1 pl-1 pr-2 w-fit`,i),children:[!c&&a?(0,r.jsx)(`img`,{src:`https://flagcdn.com/w40/${a}.png`,alt:a,onError:()=>s(a),className:`w-5 h-3.5 object-cover rounded-sm shadow-sm`}):(0,r.jsx)(S,{className:`w-3.5 h-3.5 text-muted-foreground`}),(0,r.jsx)(`span`,{className:`text-xs font-bold uppercase tracking-tight leading-none`,children:e})]})};Object.defineProperty(exports,"A",{enumerable:!0,get:function(){return N}}),Object.defineProperty(exports,"B",{enumerable:!0,get:function(){return x}}),Object.defineProperty(exports,"C",{enumerable:!0,get:function(){return G}}),Object.defineProperty(exports,"D",{enumerable:!0,get:function(){return te}}),Object.defineProperty(exports,"E",{enumerable:!0,get:function(){return I}}),Object.defineProperty(exports,"F",{enumerable:!0,get:function(){return M}}),Object.defineProperty(exports,"H",{enumerable:!0,get:function(){return y}}),Object.defineProperty(exports,"I",{enumerable:!0,get:function(){return ne}}),Object.defineProperty(exports,"L",{enumerable:!0,get:function(){return T}}),Object.defineProperty(exports,"M",{enumerable:!0,get:function(){return A}}),Object.defineProperty(exports,"N",{enumerable:!0,get:function(){return O}}),Object.defineProperty(exports,"O",{enumerable:!0,get:function(){return D}}),Object.defineProperty(exports,"P",{enumerable:!0,get:function(){return E}}),Object.defineProperty(exports,"R",{enumerable:!0,get:function(){return w}}),Object.defineProperty(exports,"S",{enumerable:!0,get:function(){return W}}),Object.defineProperty(exports,"T",{enumerable:!0,get:function(){return K}}),Object.defineProperty(exports,"V",{enumerable:!0,get:function(){return b}}),Object.defineProperty(exports,"_",{enumerable:!0,get:function(){return re}}),Object.defineProperty(exports,"a",{enumerable:!0,get:function(){return se}}),Object.defineProperty(exports,"b",{enumerable:!0,get:function(){return H}}),Object.defineProperty(exports,"c",{enumerable:!0,get:function(){return ie}}),Object.defineProperty(exports,"d",{enumerable:!0,get:function(){return J}}),Object.defineProperty(exports,"f",{enumerable:!0,get:function(){return P}}),Object.defineProperty(exports,"g",{enumerable:!0,get:function(){return z}}),Object.defineProperty(exports,"h",{enumerable:!0,get:function(){return R}}),Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return ae}}),Object.defineProperty(exports,"j",{enumerable:!0,get:function(){return j}}),Object.defineProperty(exports,"k",{enumerable:!0,get:function(){return k}}),Object.defineProperty(exports,"l",{enumerable:!0,get:function(){return X}}),Object.defineProperty(exports,"m",{enumerable:!0,get:function(){return L}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return $}}),Object.defineProperty(exports,"o",{enumerable:!0,get:function(){return Z}}),Object.defineProperty(exports,"p",{enumerable:!0,get:function(){return B}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return ce}}),Object.defineProperty(exports,"s",{enumerable:!0,get:function(){return oe}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return ue}}),Object.defineProperty(exports,"u",{enumerable:!0,get:function(){return Y}}),Object.defineProperty(exports,"v",{enumerable:!0,get:function(){return F}}),Object.defineProperty(exports,"w",{enumerable:!0,get:function(){return q}}),Object.defineProperty(exports,"x",{enumerable:!0,get:function(){return U}}),Object.defineProperty(exports,"y",{enumerable:!0,get:function(){return V}}),Object.defineProperty(exports,"z",{enumerable:!0,get:function(){return C}});
|