@birdapi/velinstyle 1.2.2 → 1.3.0

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.
Files changed (109) hide show
  1. package/README.de.md +18 -4
  2. package/README.md +42 -7
  3. package/cli/cli-manifest.json +441 -174
  4. package/cli/docgen/extract-cli.js +2 -1
  5. package/cli/docs-generate.js +9 -0
  6. package/cli/experience.js +173 -0
  7. package/cli/index.js +1294 -417
  8. package/cli/motion.js +738 -0
  9. package/cli/production/extract.js +46 -6
  10. package/cli/production/report.js +104 -14
  11. package/cli/production/run.js +44 -1
  12. package/cli/security.js +190 -0
  13. package/cli/skills.js +53 -10
  14. package/cli/transparency.js +140 -41
  15. package/cli/workflow.js +32 -17
  16. package/components/velin-theme-toggle.js +15 -1
  17. package/core/a11y/component-contracts.json +391 -274
  18. package/core/attributes/registry.js +1 -1
  19. package/core/motion/analyze.js +38 -0
  20. package/core/motion/blueprint.js +51 -0
  21. package/core/motion/composer.js +114 -0
  22. package/core/motion/data/registry.json +352 -0
  23. package/core/motion/effects.js +17 -1
  24. package/core/motion/index.js +112 -9
  25. package/core/motion/optimize.js +44 -0
  26. package/core/motion/policy.js +77 -0
  27. package/core/motion/registry.js +131 -0
  28. package/core/motion/review.js +59 -0
  29. package/core/motion/scan.js +150 -0
  30. package/core/motion/timeline.js +68 -0
  31. package/core/motion/transitions.js +49 -0
  32. package/core/motion/triggers.js +168 -0
  33. package/core/security/checks/fs.js +92 -0
  34. package/core/security/detect.js +35 -0
  35. package/core/security/engine.js +116 -0
  36. package/core/security/index.js +18 -0
  37. package/core/security/registry.js +85 -0
  38. package/core/security/report/report.js +113 -0
  39. package/core/security/rules/ci/index.js +146 -0
  40. package/core/security/rules/consumer/index.js +174 -0
  41. package/core/security/rules/deps/index.js +182 -0
  42. package/core/security/rules/index.js +24 -0
  43. package/core/security/rules/publish/index.js +230 -0
  44. package/core/security/rules/repo/index.js +143 -0
  45. package/core/security/rules/secrets/index.js +133 -0
  46. package/core/security/score/dependency-health.js +53 -0
  47. package/core/security/score/release-health.js +66 -0
  48. package/core/security/score/score.js +102 -0
  49. package/core/security/timeline/timeline.js +76 -0
  50. package/dist/chunks/attributes-HK7VIOLA.js +1080 -0
  51. package/dist/chunks/attributes-VRHHVNDO.js +1080 -0
  52. package/dist/chunks/chunk-MYKUI364.js +116 -0
  53. package/dist/chunks/chunk-NEVBPD5T.js +116 -0
  54. package/dist/chunks/runtime-entry.js +1 -1
  55. package/dist/chunks/velin-theme-toggle-J2NHC7IM.js +304 -0
  56. package/dist/llms.txt +2 -2
  57. package/dist/search-index.json +166 -2
  58. package/dist/velin-agent.json +156 -32
  59. package/dist/velinstyle-components.iife.js +862 -17
  60. package/dist/velinstyle-components.js +862 -17
  61. package/dist/velinstyle-components.min.js +126 -126
  62. package/dist/velinstyle.css +42 -7
  63. package/dist/velinstyle.min.css +1 -1
  64. package/package.json +158 -143
  65. package/packages/velinstyle-cli-core/package.json +11 -0
  66. package/packages/velinstyle-cli-core/src/config.js +84 -0
  67. package/packages/velinstyle-cli-core/src/contract.js +56 -0
  68. package/packages/velinstyle-cli-core/src/event-bus.js +50 -0
  69. package/packages/velinstyle-cli-core/src/index.js +18 -0
  70. package/packages/velinstyle-cli-core/src/lifecycle.js +33 -0
  71. package/packages/velinstyle-cli-core/src/runner.js +129 -0
  72. package/packages/velinstyle-cli-registry/data/commands.json +1216 -0
  73. package/packages/velinstyle-cli-registry/data/layouts.json +33 -0
  74. package/packages/velinstyle-cli-registry/data/widgets.json +35 -0
  75. package/packages/velinstyle-cli-registry/package.json +13 -0
  76. package/packages/velinstyle-cli-registry/src/index.js +88 -0
  77. package/packages/velinstyle-cli-renderer/package.json +8 -0
  78. package/packages/velinstyle-cli-renderer/src/index.js +286 -0
  79. package/packages/velinstyle-cli-theme/package.json +8 -0
  80. package/packages/velinstyle-cli-theme/src/index.js +84 -0
  81. package/packages/velinstyle-cli-ui/package.json +8 -0
  82. package/packages/velinstyle-cli-ui/src/index.js +34 -0
  83. package/packages/velinstyle-motion/README.md +81 -0
  84. package/packages/velinstyle-motion/package.json +37 -0
  85. package/packages/velinstyle-motion/src/ai/mini-prompt.js +119 -0
  86. package/packages/velinstyle-motion/src/ai/provider.js +59 -0
  87. package/packages/velinstyle-motion/src/ai/providers/pixverse-setup.js +402 -0
  88. package/packages/velinstyle-motion/src/ai/providers/pixverse.js +245 -0
  89. package/packages/velinstyle-motion/src/config.js +257 -0
  90. package/packages/velinstyle-motion/src/export/html-clip.js +141 -0
  91. package/packages/velinstyle-motion/src/index.js +304 -0
  92. package/packages/velinstyle-motion/src/jobs/cache.js +30 -0
  93. package/packages/velinstyle-motion/src/jobs/queue.js +69 -0
  94. package/packages/velinstyle-motion/src/jobs/usage.js +53 -0
  95. package/packages/velinstyle-motion/src/local/effects.js +139 -0
  96. package/packages/velinstyle-motion/src/local/engine.js +96 -0
  97. package/packages/velinstyle-motion/src/providers-catalog.js +44 -0
  98. package/packages/velinstyle-motion/src/registry/presets.js +25 -0
  99. package/packages/velinstyle-motion/src/registry/presets.json +85 -0
  100. package/packages/velinstyle-motion/src/ux/cost-gate.js +37 -0
  101. package/packages/velinstyle-motion/src/ux/pixverse-gate.js +153 -0
  102. package/packages/velinstyle-motion/src/ux/wizard.js +171 -0
  103. package/packages/velinstyle-motion/src/validate-image.js +91 -0
  104. package/packages/velinstyle-skills/catalog.json +1 -1
  105. package/packages/velinstyle-skills/registry.json +1 -142
  106. package/packages/velinstyle-skills/skills/velin-motion-reduced-safe/SKILL.md +1 -1
  107. package/packages/velinstyle-skills/skills/velin-motion-reveal-feedback/SKILL.md +1 -1
  108. package/src/tokens/motion.css +7 -0
  109. package/src/utilities/scroll-animation.css +66 -0
@@ -0,0 +1,116 @@
1
+ // components/runtime/component-loaders.js
2
+ var COMPONENT_LOADERS = {
3
+ "velin-accordion": () => import("./velin-accordion-WSY6BMLA.js"),
4
+ "velin-announcer": () => import("./velin-announcer-PVTXXCWR.js"),
5
+ "velin-bottom-nav": () => import("./velin-bottom-nav-N5F4UO2I.js"),
6
+ "velin-calendar": () => import("./velin-calendar-XC7JRDSH.js"),
7
+ "velin-carousel": () => import("./velin-carousel-ZTBANFQQ.js"),
8
+ "velin-code-block": () => import("./velin-code-block-ZGWG7JI5.js"),
9
+ "velin-collapse": () => import("./velin-collapse-5XYBUIID.js"),
10
+ "velin-combobox": () => import("./velin-combobox-56V2ZWT5.js"),
11
+ "velin-command": () => import("./velin-command-ZJSLPK7B.js"),
12
+ "velin-copy": () => import("./velin-copy-XDQSV2XU.js"),
13
+ "velin-countdown": () => import("./velin-countdown-V4Z5MA63.js"),
14
+ "velin-counter": () => import("./velin-counter-L5FYJF7A.js"),
15
+ "velin-data-table": () => import("./velin-data-table-UVR42UUM.js"),
16
+ "velin-dialog": () => import("./velin-dialog-3YK2RPRV.js"),
17
+ "velin-drawer": () => import("./velin-drawer-A7Q7EBOS.js"),
18
+ "velin-dropdown": () => import("./velin-dropdown-PLUIFA5M.js"),
19
+ "velin-email": () => import("./velin-email-TNFONXPW.js"),
20
+ "velin-empty-state": () => import("./velin-empty-state-3NTUH2RF.js"),
21
+ "velin-file-dropzone": () => import("./velin-file-dropzone-QRGF2JNA.js"),
22
+ "velin-form-summary": () => import("./velin-form-summary-XRQ7COQH.js"),
23
+ "velin-icon": () => import("./velin-icon-A6NCXGUK.js"),
24
+ "velin-lightbox": () => import("./velin-lightbox-P725FLTY.js"),
25
+ "velin-live-dot": () => import("./velin-live-dot-RJHX2DGY.js"),
26
+ "velin-menubar": () => import("./velin-menubar-6I2LM5HL.js"),
27
+ "velin-modal": () => import("./velin-modal-3MV4FYBK.js"),
28
+ "velin-otp-input": () => import("./velin-otp-input-PSK42MM6.js"),
29
+ "velin-password-strength": () => import("./velin-password-strength-TAXMLSED.js"),
30
+ "velin-persist": () => import("./velin-persist-DFPL3QP4.js"),
31
+ "velin-popover": () => import("./velin-popover-WZG2GHBL.js"),
32
+ "velin-progress-ring": () => import("./velin-progress-ring-E4YRLZHH.js"),
33
+ "velin-rating": () => import("./velin-rating-QBBYRRBU.js"),
34
+ "velin-scroll-top": () => import("./velin-scroll-top-OHYVVHHY.js"),
35
+ "velin-scrollspy": () => import("./velin-scrollspy-OKCT4FDV.js"),
36
+ "velin-search": () => import("./velin-search-L3UG6NDQ.js"),
37
+ "velin-secure-field": () => import("./velin-secure-field-DGYMP7OK.js"),
38
+ "velin-segmented-control": () => import("./velin-segmented-control-P74GJPAR.js"),
39
+ "velin-sheet": () => import("./velin-sheet-N2VVYXFP.js"),
40
+ "velin-sparkline": () => import("./velin-sparkline-XVTFC6GE.js"),
41
+ "velin-stepper": () => import("./velin-stepper-4YQJUHPC.js"),
42
+ "velin-stepper-wc": () => import("./velin-stepper-4YQJUHPC.js"),
43
+ "velin-tabs": () => import("./velin-tabs-5UQ5ZVMV.js"),
44
+ "velin-theme-toggle": () => import("./velin-theme-toggle-J2NHC7IM.js"),
45
+ "velin-toast": () => import("./velin-toast-UG5LWTG2.js"),
46
+ "velin-tooltip": () => import("./velin-tooltip-ZDH5SDLU.js"),
47
+ "velin-tooltip-wc": () => import("./velin-tooltip-ZDH5SDLU.js")
48
+ };
49
+
50
+ // components/runtime/index.js
51
+ var registry = /* @__PURE__ */ new Map();
52
+ var VELIN_TAG_RE = /^velin-[a-z0-9-]+$/;
53
+ function whenDefined(tagName) {
54
+ if (typeof customElements === "undefined") {
55
+ return Promise.reject(new Error("customElements not available"));
56
+ }
57
+ return customElements.whenDefined(tagName);
58
+ }
59
+ async function lazyDefine(tagName) {
60
+ const loader = COMPONENT_LOADERS[tagName];
61
+ if (!loader) {
62
+ throw new Error(`Unknown Velin component: ${tagName}`);
63
+ }
64
+ if (registry.has(tagName)) return registry.get(tagName);
65
+ const p = loader().then((mod) => {
66
+ const Cls = mod.default;
67
+ if (Cls && !customElements.get(tagName)) {
68
+ customElements.define(tagName, Cls);
69
+ }
70
+ return Cls;
71
+ });
72
+ registry.set(tagName, p);
73
+ return p;
74
+ }
75
+ async function register(tagNames) {
76
+ return Promise.all(tagNames.map((t) => lazyDefine(t)));
77
+ }
78
+ function collectTagsFromDOM(root) {
79
+ const tags = /* @__PURE__ */ new Set();
80
+ root.querySelectorAll("[data-velin-component]").forEach((el) => {
81
+ const name = el.getAttribute("data-velin-component");
82
+ if (name) tags.add(name.startsWith("velin-") ? name : `velin-${name}`);
83
+ });
84
+ for (const el of root.querySelectorAll("*")) {
85
+ const tag = el.tagName?.toLowerCase();
86
+ if (tag && VELIN_TAG_RE.test(tag) && COMPONENT_LOADERS[tag]) {
87
+ tags.add(tag);
88
+ }
89
+ }
90
+ return tags;
91
+ }
92
+ async function bootFromDOM(root = document, options = {}) {
93
+ const tags = options.tags?.length ? new Set(options.tags) : collectTagsFromDOM(root);
94
+ const wcPromise = register([...tags]);
95
+ if (options.attributes) {
96
+ const { bootAttributes } = await import("./attributes-HK7VIOLA.js");
97
+ await bootAttributes(root);
98
+ }
99
+ if (options.highlight) {
100
+ const { initHighlight } = await import("./highlight-M2ELQNYK.js");
101
+ initHighlight(root);
102
+ }
103
+ if (options.haptic) {
104
+ const { VelinHapticObserver } = await import("./velin-haptic-4QQTM3RK.js");
105
+ new VelinHapticObserver().start(root instanceof Document ? root.body : root);
106
+ }
107
+ return wcPromise;
108
+ }
109
+
110
+ export {
111
+ COMPONENT_LOADERS,
112
+ whenDefined,
113
+ lazyDefine,
114
+ register,
115
+ bootFromDOM
116
+ };
@@ -0,0 +1,116 @@
1
+ // components/runtime/component-loaders.js
2
+ var COMPONENT_LOADERS = {
3
+ "velin-accordion": () => import("./velin-accordion-WSY6BMLA.js"),
4
+ "velin-announcer": () => import("./velin-announcer-PVTXXCWR.js"),
5
+ "velin-bottom-nav": () => import("./velin-bottom-nav-N5F4UO2I.js"),
6
+ "velin-calendar": () => import("./velin-calendar-XC7JRDSH.js"),
7
+ "velin-carousel": () => import("./velin-carousel-ZTBANFQQ.js"),
8
+ "velin-code-block": () => import("./velin-code-block-ZGWG7JI5.js"),
9
+ "velin-collapse": () => import("./velin-collapse-5XYBUIID.js"),
10
+ "velin-combobox": () => import("./velin-combobox-56V2ZWT5.js"),
11
+ "velin-command": () => import("./velin-command-ZJSLPK7B.js"),
12
+ "velin-copy": () => import("./velin-copy-XDQSV2XU.js"),
13
+ "velin-countdown": () => import("./velin-countdown-V4Z5MA63.js"),
14
+ "velin-counter": () => import("./velin-counter-L5FYJF7A.js"),
15
+ "velin-data-table": () => import("./velin-data-table-UVR42UUM.js"),
16
+ "velin-dialog": () => import("./velin-dialog-3YK2RPRV.js"),
17
+ "velin-drawer": () => import("./velin-drawer-A7Q7EBOS.js"),
18
+ "velin-dropdown": () => import("./velin-dropdown-PLUIFA5M.js"),
19
+ "velin-email": () => import("./velin-email-TNFONXPW.js"),
20
+ "velin-empty-state": () => import("./velin-empty-state-3NTUH2RF.js"),
21
+ "velin-file-dropzone": () => import("./velin-file-dropzone-QRGF2JNA.js"),
22
+ "velin-form-summary": () => import("./velin-form-summary-XRQ7COQH.js"),
23
+ "velin-icon": () => import("./velin-icon-A6NCXGUK.js"),
24
+ "velin-lightbox": () => import("./velin-lightbox-P725FLTY.js"),
25
+ "velin-live-dot": () => import("./velin-live-dot-RJHX2DGY.js"),
26
+ "velin-menubar": () => import("./velin-menubar-6I2LM5HL.js"),
27
+ "velin-modal": () => import("./velin-modal-3MV4FYBK.js"),
28
+ "velin-otp-input": () => import("./velin-otp-input-PSK42MM6.js"),
29
+ "velin-password-strength": () => import("./velin-password-strength-TAXMLSED.js"),
30
+ "velin-persist": () => import("./velin-persist-DFPL3QP4.js"),
31
+ "velin-popover": () => import("./velin-popover-WZG2GHBL.js"),
32
+ "velin-progress-ring": () => import("./velin-progress-ring-E4YRLZHH.js"),
33
+ "velin-rating": () => import("./velin-rating-QBBYRRBU.js"),
34
+ "velin-scroll-top": () => import("./velin-scroll-top-OHYVVHHY.js"),
35
+ "velin-scrollspy": () => import("./velin-scrollspy-OKCT4FDV.js"),
36
+ "velin-search": () => import("./velin-search-L3UG6NDQ.js"),
37
+ "velin-secure-field": () => import("./velin-secure-field-DGYMP7OK.js"),
38
+ "velin-segmented-control": () => import("./velin-segmented-control-P74GJPAR.js"),
39
+ "velin-sheet": () => import("./velin-sheet-N2VVYXFP.js"),
40
+ "velin-sparkline": () => import("./velin-sparkline-XVTFC6GE.js"),
41
+ "velin-stepper": () => import("./velin-stepper-4YQJUHPC.js"),
42
+ "velin-stepper-wc": () => import("./velin-stepper-4YQJUHPC.js"),
43
+ "velin-tabs": () => import("./velin-tabs-5UQ5ZVMV.js"),
44
+ "velin-theme-toggle": () => import("./velin-theme-toggle-32J2CBNC.js"),
45
+ "velin-toast": () => import("./velin-toast-UG5LWTG2.js"),
46
+ "velin-tooltip": () => import("./velin-tooltip-ZDH5SDLU.js"),
47
+ "velin-tooltip-wc": () => import("./velin-tooltip-ZDH5SDLU.js")
48
+ };
49
+
50
+ // components/runtime/index.js
51
+ var registry = /* @__PURE__ */ new Map();
52
+ var VELIN_TAG_RE = /^velin-[a-z0-9-]+$/;
53
+ function whenDefined(tagName) {
54
+ if (typeof customElements === "undefined") {
55
+ return Promise.reject(new Error("customElements not available"));
56
+ }
57
+ return customElements.whenDefined(tagName);
58
+ }
59
+ async function lazyDefine(tagName) {
60
+ const loader = COMPONENT_LOADERS[tagName];
61
+ if (!loader) {
62
+ throw new Error(`Unknown Velin component: ${tagName}`);
63
+ }
64
+ if (registry.has(tagName)) return registry.get(tagName);
65
+ const p = loader().then((mod) => {
66
+ const Cls = mod.default;
67
+ if (Cls && !customElements.get(tagName)) {
68
+ customElements.define(tagName, Cls);
69
+ }
70
+ return Cls;
71
+ });
72
+ registry.set(tagName, p);
73
+ return p;
74
+ }
75
+ async function register(tagNames) {
76
+ return Promise.all(tagNames.map((t) => lazyDefine(t)));
77
+ }
78
+ function collectTagsFromDOM(root) {
79
+ const tags = /* @__PURE__ */ new Set();
80
+ root.querySelectorAll("[data-velin-component]").forEach((el) => {
81
+ const name = el.getAttribute("data-velin-component");
82
+ if (name) tags.add(name.startsWith("velin-") ? name : `velin-${name}`);
83
+ });
84
+ for (const el of root.querySelectorAll("*")) {
85
+ const tag = el.tagName?.toLowerCase();
86
+ if (tag && VELIN_TAG_RE.test(tag) && COMPONENT_LOADERS[tag]) {
87
+ tags.add(tag);
88
+ }
89
+ }
90
+ return tags;
91
+ }
92
+ async function bootFromDOM(root = document, options = {}) {
93
+ const tags = options.tags?.length ? new Set(options.tags) : collectTagsFromDOM(root);
94
+ const wcPromise = register([...tags]);
95
+ if (options.attributes) {
96
+ const { bootAttributes } = await import("./attributes-VRHHVNDO.js");
97
+ await bootAttributes(root);
98
+ }
99
+ if (options.highlight) {
100
+ const { initHighlight } = await import("./highlight-M2ELQNYK.js");
101
+ initHighlight(root);
102
+ }
103
+ if (options.haptic) {
104
+ const { VelinHapticObserver } = await import("./velin-haptic-4QQTM3RK.js");
105
+ new VelinHapticObserver().start(root instanceof Document ? root.body : root);
106
+ }
107
+ return wcPromise;
108
+ }
109
+
110
+ export {
111
+ COMPONENT_LOADERS,
112
+ whenDefined,
113
+ lazyDefine,
114
+ register,
115
+ bootFromDOM
116
+ };
@@ -4,7 +4,7 @@ import {
4
4
  lazyDefine,
5
5
  register,
6
6
  whenDefined
7
- } from "./chunk-Y6HN7HWX.js";
7
+ } from "./chunk-MYKUI364.js";
8
8
  export {
9
9
  COMPONENT_LOADERS,
10
10
  bootFromDOM,
@@ -0,0 +1,304 @@
1
+ // components/velin-theme-toggle.js
2
+ var THEMES = [
3
+ { slug: "", label: "Default (Light)" },
4
+ { slug: "dark", label: "Dark" },
5
+ { slug: "brutalist", label: "Brutalist" },
6
+ { slug: "corporate", label: "Corporate" },
7
+ { slug: "earth", label: "Earth" },
8
+ { slug: "forest", label: "Forest" },
9
+ { slug: "midnight", label: "Midnight" },
10
+ { slug: "neon", label: "Neon" },
11
+ { slug: "nordic", label: "Nordic" },
12
+ { slug: "ocean", label: "Ocean" },
13
+ { slug: "pastel", label: "Pastel" },
14
+ { slug: "retro", label: "Retro" },
15
+ { slug: "sharp", label: "Sharp" },
16
+ { slug: "soft", label: "Soft" },
17
+ { slug: "sunset", label: "Sunset" }
18
+ ];
19
+ var BUILTIN_THEMES = /* @__PURE__ */ new Set(["", "dark"]);
20
+ var DARK_THEME_SLUGS = /* @__PURE__ */ new Set(["dark", "midnight", "neon"]);
21
+ var loadedThemeStylesheets = /* @__PURE__ */ new Set();
22
+ function applyColorScheme(target, slug) {
23
+ const dark = DARK_THEME_SLUGS.has(slug);
24
+ if (target === document.documentElement || target === document.body) {
25
+ target.style.colorScheme = dark ? "dark" : "light";
26
+ }
27
+ target.setAttribute("data-velin-color-scheme", dark ? "dark" : "light");
28
+ }
29
+ function ensureThemeStylesheet(slug, base) {
30
+ if (!slug || BUILTIN_THEMES.has(slug)) return;
31
+ if (loadedThemeStylesheets.has(slug)) return;
32
+ const existing = document.querySelector(`link[data-velin-theme-css="${slug}"]`);
33
+ if (existing) {
34
+ loadedThemeStylesheets.add(slug);
35
+ return;
36
+ }
37
+ const link = document.createElement("link");
38
+ link.rel = "stylesheet";
39
+ link.href = `${base.replace(/\/$/, "")}/${slug}.min.css`;
40
+ link.setAttribute("data-velin-theme-css", slug);
41
+ document.head.appendChild(link);
42
+ loadedThemeStylesheets.add(slug);
43
+ }
44
+ var styles = `
45
+ :host { display: inline-flex; position: relative; }
46
+ .group {
47
+ display: inline-flex; align-items: stretch;
48
+ border: 2px solid var(--velin-color-border, #ddd);
49
+ border-radius: var(--velin-radius-md, 0.5rem);
50
+ background: none;
51
+ overflow: hidden;
52
+ }
53
+ button {
54
+ display: inline-flex; align-items: center; justify-content: center;
55
+ min-height: 2.75rem; padding: 0.5rem;
56
+ background: none; border: 0; cursor: pointer;
57
+ color: var(--velin-color-text, #111);
58
+ transition: background 150ms ease;
59
+ }
60
+ button:hover { background: var(--velin-color-surface-dim, #eee); }
61
+ button:focus-visible {
62
+ outline: 3px solid var(--velin-color-focus, #2563eb);
63
+ outline-offset: 2px;
64
+ }
65
+ .toggle { min-width: 2.75rem; }
66
+ .picker {
67
+ min-width: 1.75rem;
68
+ border-inline-start: 1px solid var(--velin-color-border, #ddd);
69
+ color: var(--velin-color-text-muted, #555);
70
+ }
71
+ svg { width: 1.25rem; height: 1.25rem; transition: transform 300ms ease; }
72
+ .chev { width: 0.75rem; height: 0.75rem; }
73
+ :host([theme="dark"]) .sun { display: none; }
74
+ :host(:not([theme="dark"])) .moon { display: none; }
75
+ :host([compact]) .picker { display: none; }
76
+ :host([compact]) .toggle { border-inline-end: 0; }
77
+ @media (prefers-reduced-motion: reduce) { svg { transition: none; } }
78
+
79
+ .menu {
80
+ position: absolute;
81
+ top: calc(100% + 0.5rem);
82
+ inset-inline-end: 0;
83
+ z-index: 1000;
84
+ min-width: 12rem;
85
+ padding: 0.375rem;
86
+ background: var(--velin-color-surface-bright, #fff);
87
+ border: 1px solid var(--velin-color-border, #ddd);
88
+ border-radius: var(--velin-radius-md, 0.5rem);
89
+ box-shadow: var(--velin-shadow-lg, 0 12px 32px rgba(0,0,0,0.12));
90
+ list-style: none;
91
+ margin: 0;
92
+ display: none;
93
+ max-height: min(70vh, 24rem);
94
+ overflow-y: auto;
95
+ }
96
+ :host([menu-open]) .menu { display: block; }
97
+ .menu li { margin: 0; }
98
+ .menu button {
99
+ width: 100%;
100
+ justify-content: flex-start;
101
+ padding: 0.4rem 0.75rem;
102
+ font-size: 0.875rem;
103
+ color: var(--velin-color-text, #111);
104
+ border-radius: var(--velin-radius-sm, 0.25rem);
105
+ min-height: 2rem;
106
+ text-align: start;
107
+ }
108
+ .menu button:hover,
109
+ .menu button[aria-current="true"] {
110
+ background: var(--velin-color-primary-subtle, #eef);
111
+ color: var(--velin-color-primary, #2a4cf0);
112
+ }
113
+ .menu button[aria-current="true"] {
114
+ font-weight: 600;
115
+ }
116
+ .menu .swatch {
117
+ width: 0.75rem; height: 0.75rem;
118
+ border-radius: 50%;
119
+ margin-inline-end: 0.5rem;
120
+ background: currentColor;
121
+ border: 1px solid var(--velin-color-border, #ddd);
122
+ }
123
+ `;
124
+ var VelinThemeToggle = class extends HTMLElement {
125
+ constructor() {
126
+ super();
127
+ this.attachShadow({ mode: "open" });
128
+ this._onDocClick = this._onDocClick.bind(this);
129
+ this._onKeyDown = this._onKeyDown.bind(this);
130
+ }
131
+ connectedCallback() {
132
+ this.shadowRoot.innerHTML = `
133
+ <style>${styles}</style>
134
+ <div class="group" part="group">
135
+ <button class="toggle" part="button" aria-label="Toggle dark mode" aria-pressed="false">
136
+ <svg class="sun" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true" focusable="false">
137
+ <circle cx="12" cy="12" r="5"/><line x1="12" y1="1" x2="12" y2="3"/><line x1="12" y1="21" x2="12" y2="23"/>
138
+ <line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/>
139
+ <line x1="1" y1="12" x2="3" y2="12"/><line x1="21" y1="12" x2="23" y2="12"/>
140
+ <line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/>
141
+ </svg>
142
+ <svg class="moon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true" focusable="false">
143
+ <path d="M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79z"/>
144
+ </svg>
145
+ </button>
146
+ <button class="picker" part="picker" aria-label="Choose theme" aria-haspopup="menu" aria-expanded="false">
147
+ <svg class="chev" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
148
+ <polyline points="6 9 12 15 18 9"/>
149
+ </svg>
150
+ </button>
151
+ </div>
152
+ <ul class="menu" role="menu" aria-label="Theme selection" hidden></ul>
153
+ `;
154
+ this._target = document.querySelector(this.getAttribute("target") || "html");
155
+ this._themesBase = this.getAttribute("themes-base") || "dist/themes";
156
+ this._menu = this.shadowRoot.querySelector(".menu");
157
+ this._toggleBtn = this.shadowRoot.querySelector(".toggle");
158
+ this._pickerBtn = this.shadowRoot.querySelector(".picker");
159
+ this._renderMenu();
160
+ this._initPreference();
161
+ this._syncTogglePressed();
162
+ this._toggleBtn.addEventListener("click", () => this._toggleDarkMode());
163
+ this._pickerBtn.addEventListener("click", (e) => {
164
+ e.stopPropagation();
165
+ this._toggleMenu();
166
+ });
167
+ document.addEventListener("click", this._onDocClick);
168
+ this.shadowRoot.addEventListener("keydown", this._onKeyDown);
169
+ const prefersDarkMq = window.matchMedia("(prefers-color-scheme: dark)");
170
+ prefersDarkMq.addEventListener("change", () => this._applyFromPreference());
171
+ window.addEventListener("storage", (e) => {
172
+ if (e.key === "velin-theme") this._readStorage();
173
+ });
174
+ }
175
+ disconnectedCallback() {
176
+ document.removeEventListener("click", this._onDocClick);
177
+ }
178
+ _renderMenu() {
179
+ this._menu.innerHTML = THEMES.map((t) => `
180
+ <li role="none">
181
+ <button type="button" role="menuitem" data-theme="${t.slug}">
182
+ <span class="swatch" aria-hidden="true" data-theme-swatch="${t.slug}"></span>
183
+ ${t.label}
184
+ </button>
185
+ </li>
186
+ `).join("");
187
+ this._menu.removeAttribute("hidden");
188
+ this._menu.querySelectorAll("button[data-theme]").forEach((btn) => {
189
+ btn.addEventListener("click", () => {
190
+ const slug = btn.getAttribute("data-theme");
191
+ this._applyTheme(slug, { persist: true });
192
+ this._closeMenu();
193
+ });
194
+ });
195
+ }
196
+ _toggleMenu() {
197
+ if (this.hasAttribute("menu-open")) this._closeMenu();
198
+ else this._openMenu();
199
+ }
200
+ _openMenu() {
201
+ this.setAttribute("menu-open", "");
202
+ this._pickerBtn.setAttribute("aria-expanded", "true");
203
+ this._highlightActive();
204
+ const first = this._menu.querySelector("button[data-theme]");
205
+ if (first) first.focus();
206
+ }
207
+ _closeMenu() {
208
+ this.removeAttribute("menu-open");
209
+ this._pickerBtn.setAttribute("aria-expanded", "false");
210
+ }
211
+ _onDocClick(e) {
212
+ if (!this.hasAttribute("menu-open")) return;
213
+ if (e.composedPath().includes(this)) return;
214
+ this._closeMenu();
215
+ }
216
+ _onKeyDown(e) {
217
+ if (!this.hasAttribute("menu-open")) return;
218
+ if (e.key === "Escape") {
219
+ e.preventDefault();
220
+ this._closeMenu();
221
+ this._pickerBtn.focus();
222
+ return;
223
+ }
224
+ if (e.key === "ArrowDown" || e.key === "ArrowUp") {
225
+ e.preventDefault();
226
+ const items = Array.from(this._menu.querySelectorAll("button[data-theme]"));
227
+ const idx = items.indexOf(this.shadowRoot.activeElement);
228
+ const next = e.key === "ArrowDown" ? items[(idx + 1) % items.length] : items[(idx - 1 + items.length) % items.length];
229
+ next?.focus();
230
+ }
231
+ }
232
+ _highlightActive() {
233
+ const current = this._currentSlug();
234
+ this._menu.querySelectorAll("button[data-theme]").forEach((btn) => {
235
+ const slug = btn.getAttribute("data-theme");
236
+ if (slug === current) btn.setAttribute("aria-current", "true");
237
+ else btn.removeAttribute("aria-current");
238
+ });
239
+ }
240
+ _currentSlug() {
241
+ if (!this._target) return "";
242
+ const value = this._target.getAttribute("data-velin-theme");
243
+ if (!value || value === "light") return "";
244
+ return value;
245
+ }
246
+ _initPreference() {
247
+ const stored = localStorage.getItem("velin-theme");
248
+ if (stored) {
249
+ this._applyTheme(stored, { persist: false });
250
+ return;
251
+ }
252
+ this._applyFromPreference();
253
+ }
254
+ _readStorage() {
255
+ const stored = localStorage.getItem("velin-theme");
256
+ this._applyTheme(stored || "", { persist: false });
257
+ }
258
+ _applyFromPreference() {
259
+ if (localStorage.getItem("velin-theme")) return;
260
+ const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
261
+ this._applyTheme(prefersDark ? "dark" : "", { persist: false });
262
+ }
263
+ _applyTheme(slug, { persist }) {
264
+ const normalized = !slug || slug === "light" ? "" : slug;
265
+ if (!this._target) return;
266
+ if (!normalized) {
267
+ this._target.removeAttribute("data-velin-theme");
268
+ this.removeAttribute("theme");
269
+ } else {
270
+ this._target.setAttribute("data-velin-theme", normalized);
271
+ this.setAttribute("theme", normalized === "dark" ? "dark" : normalized);
272
+ ensureThemeStylesheet(normalized, this._themesBase);
273
+ }
274
+ applyColorScheme(this._target, normalized);
275
+ if (persist) {
276
+ if (!normalized) localStorage.removeItem("velin-theme");
277
+ else localStorage.setItem("velin-theme", normalized);
278
+ }
279
+ this._highlightActive();
280
+ this.dispatchEvent(new CustomEvent("velin-theme-change", {
281
+ bubbles: true,
282
+ detail: {
283
+ theme: normalized || "light",
284
+ dark: DARK_THEME_SLUGS.has(normalized),
285
+ slug: normalized
286
+ }
287
+ }));
288
+ }
289
+ _syncTogglePressed() {
290
+ const dark = this._currentSlug() === "dark";
291
+ this._toggleBtn?.setAttribute("aria-pressed", dark ? "true" : "false");
292
+ }
293
+ _toggleDarkMode() {
294
+ const current = this._currentSlug();
295
+ const next = current === "dark" ? "" : "dark";
296
+ this._applyTheme(next, { persist: true });
297
+ this._syncTogglePressed();
298
+ }
299
+ };
300
+ customElements.define("velin-theme-toggle", VelinThemeToggle);
301
+ var velin_theme_toggle_default = VelinThemeToggle;
302
+ export {
303
+ velin_theme_toggle_default as default
304
+ };
package/dist/llms.txt CHANGED
@@ -1,4 +1,4 @@
1
- # VelinStyle 1.2.2
1
+ # VelinStyle 1.3.0
2
2
 
3
3
  > VelinStyle is a CSS framework with WCAG 2.2 AAA-oriented defaults, native JavaScript runtime, and Web Components.
4
4
  > Full machine context: https://velinstyle.info/dist/velin-agent.json
@@ -11,7 +11,7 @@
11
11
  - Maturity: CSS/Web Components/runtime = stable; plan/review, knowledge graph, page/section registry, agent metadata = beta/foundation (seed, expanding); Studio + Utility Engine generator = planned
12
12
  - Components: 43 canonical Web Components (`velin-*`); 45 lazy-loader entries
13
13
  - Knowledge graph: 20 component nodes, 17 page types, 12 sections, 3 design constraint packs
14
- - HTML attributes: 29 `velin-*` bridges
14
+ - HTML attributes: 36 `velin-*` bridges
15
15
  - CLI: velinstyle (scan, scaffold, plan, review, docs generate, search index, meta)
16
16
 
17
17
  ## Agent briefing