@vegastack/design 0.1.0 → 0.2.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.
- package/bin/check-updates.mjs +706 -108
- package/bin/skills.mjs +262 -0
- package/bin/vegastack-design.mjs +32 -14
- package/bin/verify-registry-item.mjs +775 -214
- package/css/base.css +1 -1
- package/css/theme.css +1 -1
- package/css/utilities.css +1 -1
- package/dist/icons/index.cjs +199 -0
- package/dist/icons/index.d.cts +164 -0
- package/dist/icons/index.d.ts +39 -29
- package/dist/icons/index.js +81 -14
- package/dist/index.cjs +78 -0
- package/dist/index.d.cts +56 -0
- package/dist/index.d.ts +7 -0
- package/dist/preset.cjs +37 -0
- package/dist/preset.d.cts +19 -0
- package/dist/theme-scope.cjs +56 -0
- package/dist/theme-scope.d.cts +23 -0
- package/dist/theme-scope.d.ts +23 -0
- package/dist/theme-scope.js +21 -0
- package/package.json +40 -18
- package/skills/vegastack-brand/SKILL.md +29 -0
- package/skills/vegastack-consume/SKILL.md +182 -0
- package/skills/vegastack-consume/references/registry-integrity.md +132 -0
- package/skills/vegastack-design-audit/SKILL.md +123 -0
- package/skills/vegastack-design-system/SKILL.md +110 -0
- package/skills/vegastack-design-system/references/components.md +151 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var src_exports = {};
|
|
22
|
+
__export(src_exports, {
|
|
23
|
+
FLOATING: () => FLOATING,
|
|
24
|
+
TIMINGS: () => TIMINGS,
|
|
25
|
+
cn: () => cn
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(src_exports);
|
|
28
|
+
var import_clsx = require("clsx");
|
|
29
|
+
var import_tailwind_merge = require("tailwind-merge");
|
|
30
|
+
var twMerge = (0, import_tailwind_merge.extendTailwindMerge)({
|
|
31
|
+
extend: {
|
|
32
|
+
classGroups: {
|
|
33
|
+
"font-size": [
|
|
34
|
+
{
|
|
35
|
+
text: [
|
|
36
|
+
"h1",
|
|
37
|
+
"h2",
|
|
38
|
+
"h3",
|
|
39
|
+
"h4",
|
|
40
|
+
"label",
|
|
41
|
+
"label-sm",
|
|
42
|
+
"code",
|
|
43
|
+
"code-sm",
|
|
44
|
+
"mono-label",
|
|
45
|
+
"display-sm",
|
|
46
|
+
"display-md",
|
|
47
|
+
"display-lg",
|
|
48
|
+
"display-xl"
|
|
49
|
+
]
|
|
50
|
+
}
|
|
51
|
+
]
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
function cn(...inputs) {
|
|
56
|
+
return twMerge((0, import_clsx.clsx)(inputs));
|
|
57
|
+
}
|
|
58
|
+
var TIMINGS = {
|
|
59
|
+
/** How long transient success feedback holds before reverting (CopyButton "Copied ✓"). */
|
|
60
|
+
feedbackRevertMs: 1500,
|
|
61
|
+
/** Debounce before auto-persisting a text field (AutoSaveInput). */
|
|
62
|
+
autoSaveDebounceMs: 800,
|
|
63
|
+
/** Hover delay before a rich preview (HoverCard) opens — guards accidental opens. */
|
|
64
|
+
hoverOpenDelayMs: 700,
|
|
65
|
+
/** Hover delay before a rich preview closes — lets the pointer travel into the card. */
|
|
66
|
+
hoverCloseDelayMs: 300
|
|
67
|
+
};
|
|
68
|
+
var FLOATING = {
|
|
69
|
+
sideOffsetAttached: 4,
|
|
70
|
+
sideOffsetDetached: 8,
|
|
71
|
+
collisionPadding: 8
|
|
72
|
+
};
|
|
73
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
74
|
+
0 && (module.exports = {
|
|
75
|
+
FLOATING,
|
|
76
|
+
TIMINGS,
|
|
77
|
+
cn
|
|
78
|
+
});
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { ClassValue } from 'clsx';
|
|
2
|
+
export { ClassValue } from 'clsx';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Merges Tailwind CSS class names with intelligent conflict resolution.
|
|
6
|
+
*
|
|
7
|
+
* Combines `clsx` for conditional classes and `tailwind-merge` to handle
|
|
8
|
+
* conflicting Tailwind utilities (e.g., `px-2` and `px-4` → keeps last one).
|
|
9
|
+
*
|
|
10
|
+
* @param inputs - Class names, objects, arrays, or conditional values
|
|
11
|
+
* @returns Merged and deduplicated class string
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* cn('px-2 py-1', 'px-4') // 'py-1 px-4'
|
|
15
|
+
* cn('text-foreground', isError && 'text-destructive')
|
|
16
|
+
*/
|
|
17
|
+
declare function cn(...inputs: ClassValue[]): string;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @internal Registry theme-scope plumbing lives at `@vegastack/design/theme-scope`, NOT here.
|
|
21
|
+
* It calls `React.createContext()` at module scope, which is `undefined` under the `react-server`
|
|
22
|
+
* condition — re-exporting it from this entry would make every Server Component that imports
|
|
23
|
+
* `cn` crash on import. This entry stays server-safe by contract (see tsup.config.ts).
|
|
24
|
+
* Product code should use `MarketingSurface` rather than either symbol.
|
|
25
|
+
*/
|
|
26
|
+
/**
|
|
27
|
+
* Interaction timing constants (ms) — design decisions, not magic numbers (register P2-14).
|
|
28
|
+
* Single source for every JS-driven delay in the registry; change one value and every
|
|
29
|
+
* component that expresses that role follows.
|
|
30
|
+
*/
|
|
31
|
+
declare const TIMINGS: {
|
|
32
|
+
/** How long transient success feedback holds before reverting (CopyButton "Copied ✓"). */
|
|
33
|
+
readonly feedbackRevertMs: 1500;
|
|
34
|
+
/** Debounce before auto-persisting a text field (AutoSaveInput). */
|
|
35
|
+
readonly autoSaveDebounceMs: 800;
|
|
36
|
+
/** Hover delay before a rich preview (HoverCard) opens — guards accidental opens. */
|
|
37
|
+
readonly hoverOpenDelayMs: 700;
|
|
38
|
+
/** Hover delay before a rich preview closes — lets the pointer travel into the card. */
|
|
39
|
+
readonly hoverCloseDelayMs: 300;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Floating-surface positioning constants (px) — the unified sideOffset/collisionPadding
|
|
43
|
+
* pair (register P2-14). Two offset roles, one collision padding:
|
|
44
|
+
* - `sideOffsetAttached` (4): menu-like popups that read as attached to their trigger
|
|
45
|
+
* (dropdown, context menu, select, emoji picker).
|
|
46
|
+
* - `sideOffsetDetached` (8): floating panels that read as detached (popover, hover-card,
|
|
47
|
+
* tooltip).
|
|
48
|
+
* Submenus deliberately use 0 (flush) and are not part of this contract.
|
|
49
|
+
*/
|
|
50
|
+
declare const FLOATING: {
|
|
51
|
+
readonly sideOffsetAttached: 4;
|
|
52
|
+
readonly sideOffsetDetached: 8;
|
|
53
|
+
readonly collisionPadding: 8;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export { FLOATING, TIMINGS, cn };
|
package/dist/index.d.ts
CHANGED
|
@@ -16,6 +16,13 @@ export { ClassValue } from 'clsx';
|
|
|
16
16
|
*/
|
|
17
17
|
declare function cn(...inputs: ClassValue[]): string;
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* @internal Registry theme-scope plumbing lives at `@vegastack/design/theme-scope`, NOT here.
|
|
21
|
+
* It calls `React.createContext()` at module scope, which is `undefined` under the `react-server`
|
|
22
|
+
* condition — re-exporting it from this entry would make every Server Component that imports
|
|
23
|
+
* `cn` crash on import. This entry stays server-safe by contract (see tsup.config.ts).
|
|
24
|
+
* Product code should use `MarketingSurface` rather than either symbol.
|
|
25
|
+
*/
|
|
19
26
|
/**
|
|
20
27
|
* Interaction timing constants (ms) — design decisions, not magic numbers (register P2-14).
|
|
21
28
|
* Single source for every JS-driven delay in the registry; change one value and every
|
package/dist/preset.cjs
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/preset.ts
|
|
21
|
+
var preset_exports = {};
|
|
22
|
+
__export(preset_exports, {
|
|
23
|
+
vegastackPreset: () => vegastackPreset
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(preset_exports);
|
|
26
|
+
var vegastackPreset = {
|
|
27
|
+
/** The token package this preset is bound to. */
|
|
28
|
+
tokens: "@vegastack/design-tokens",
|
|
29
|
+
/** CSS entry consumers import to get the full setup. */
|
|
30
|
+
css: "@vegastack/design/preset.css",
|
|
31
|
+
/** Tailwind major version this preset targets. */
|
|
32
|
+
tailwind: 4
|
|
33
|
+
};
|
|
34
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
35
|
+
0 && (module.exports = {
|
|
36
|
+
vegastackPreset
|
|
37
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@vegastack/design/preset` — Tailwind v4 setup metadata for VegaStack.
|
|
3
|
+
*
|
|
4
|
+
* Tailwind v4 is CSS-first (no JS `presets` array), so the real "preset" is the
|
|
5
|
+
* shipped `preset.css` (`@import "@vegastack/design/preset.css"`), which
|
|
6
|
+
* wires Tailwind + tw-animate-css + the VegaStack token theme + base reset in one
|
|
7
|
+
* import. This module exposes machine-readable metadata for tooling/agents.
|
|
8
|
+
*/
|
|
9
|
+
declare const vegastackPreset: {
|
|
10
|
+
/** The token package this preset is bound to. */
|
|
11
|
+
readonly tokens: "@vegastack/design-tokens";
|
|
12
|
+
/** CSS entry consumers import to get the full setup. */
|
|
13
|
+
readonly css: "@vegastack/design/preset.css";
|
|
14
|
+
/** Tailwind major version this preset targets. */
|
|
15
|
+
readonly tailwind: 4;
|
|
16
|
+
};
|
|
17
|
+
type VegastackPreset = typeof vegastackPreset;
|
|
18
|
+
|
|
19
|
+
export { type VegastackPreset, vegastackPreset };
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
"use client";
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __export = (target, all) => {
|
|
10
|
+
for (var name in all)
|
|
11
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
12
|
+
};
|
|
13
|
+
var __copyProps = (to, from, except, desc) => {
|
|
14
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
+
for (let key of __getOwnPropNames(from))
|
|
16
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
17
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
18
|
+
}
|
|
19
|
+
return to;
|
|
20
|
+
};
|
|
21
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
22
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
23
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
24
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
25
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
26
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
27
|
+
mod
|
|
28
|
+
));
|
|
29
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
30
|
+
|
|
31
|
+
// src/theme-scope.tsx
|
|
32
|
+
var theme_scope_exports = {};
|
|
33
|
+
__export(theme_scope_exports, {
|
|
34
|
+
InternalThemeScopeProvider: () => InternalThemeScopeProvider,
|
|
35
|
+
useInternalThemeScope: () => useInternalThemeScope
|
|
36
|
+
});
|
|
37
|
+
module.exports = __toCommonJS(theme_scope_exports);
|
|
38
|
+
var React = __toESM(require("react"), 1);
|
|
39
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
40
|
+
var InternalThemeScopeContext = React.createContext(
|
|
41
|
+
void 0
|
|
42
|
+
);
|
|
43
|
+
function InternalThemeScopeProvider({
|
|
44
|
+
children,
|
|
45
|
+
scope
|
|
46
|
+
}) {
|
|
47
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InternalThemeScopeContext.Provider, { value: scope, children });
|
|
48
|
+
}
|
|
49
|
+
function useInternalThemeScope() {
|
|
50
|
+
return React.useContext(InternalThemeScopeContext);
|
|
51
|
+
}
|
|
52
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
53
|
+
0 && (module.exports = {
|
|
54
|
+
InternalThemeScopeProvider,
|
|
55
|
+
useInternalThemeScope
|
|
56
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Carries a semantic theme-scope class through React's tree, including across
|
|
5
|
+
* portals whose DOM nodes are mounted outside the scoped source subtree.
|
|
6
|
+
*
|
|
7
|
+
* @internal Registry infrastructure only. This is not a consumer-facing
|
|
8
|
+
* theming API; use `MarketingSurface` to establish the supported scope.
|
|
9
|
+
*/
|
|
10
|
+
declare function InternalThemeScopeProvider({ children, scope, }: {
|
|
11
|
+
children: React.ReactNode;
|
|
12
|
+
scope: string;
|
|
13
|
+
}): React.JSX.Element;
|
|
14
|
+
/**
|
|
15
|
+
* Reads the nearest semantic theme-scope class so portaled surfaces can apply
|
|
16
|
+
* it to their actual DOM roots instead of falling back to the page theme.
|
|
17
|
+
*
|
|
18
|
+
* @internal Registry infrastructure only. Components outside the canonical
|
|
19
|
+
* overlay implementations must not depend on this hook.
|
|
20
|
+
*/
|
|
21
|
+
declare function useInternalThemeScope(): string | undefined;
|
|
22
|
+
|
|
23
|
+
export { InternalThemeScopeProvider, useInternalThemeScope };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Carries a semantic theme-scope class through React's tree, including across
|
|
5
|
+
* portals whose DOM nodes are mounted outside the scoped source subtree.
|
|
6
|
+
*
|
|
7
|
+
* @internal Registry infrastructure only. This is not a consumer-facing
|
|
8
|
+
* theming API; use `MarketingSurface` to establish the supported scope.
|
|
9
|
+
*/
|
|
10
|
+
declare function InternalThemeScopeProvider({ children, scope, }: {
|
|
11
|
+
children: React.ReactNode;
|
|
12
|
+
scope: string;
|
|
13
|
+
}): React.JSX.Element;
|
|
14
|
+
/**
|
|
15
|
+
* Reads the nearest semantic theme-scope class so portaled surfaces can apply
|
|
16
|
+
* it to their actual DOM roots instead of falling back to the page theme.
|
|
17
|
+
*
|
|
18
|
+
* @internal Registry infrastructure only. Components outside the canonical
|
|
19
|
+
* overlay implementations must not depend on this hook.
|
|
20
|
+
*/
|
|
21
|
+
declare function useInternalThemeScope(): string | undefined;
|
|
22
|
+
|
|
23
|
+
export { InternalThemeScopeProvider, useInternalThemeScope };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/theme-scope.tsx
|
|
4
|
+
import * as React from "react";
|
|
5
|
+
import { jsx } from "react/jsx-runtime";
|
|
6
|
+
var InternalThemeScopeContext = React.createContext(
|
|
7
|
+
void 0
|
|
8
|
+
);
|
|
9
|
+
function InternalThemeScopeProvider({
|
|
10
|
+
children,
|
|
11
|
+
scope
|
|
12
|
+
}) {
|
|
13
|
+
return /* @__PURE__ */ jsx(InternalThemeScopeContext.Provider, { value: scope, children });
|
|
14
|
+
}
|
|
15
|
+
function useInternalThemeScope() {
|
|
16
|
+
return React.useContext(InternalThemeScopeContext);
|
|
17
|
+
}
|
|
18
|
+
export {
|
|
19
|
+
InternalThemeScopeProvider,
|
|
20
|
+
useInternalThemeScope
|
|
21
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vegastack/design",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "VegaStack design system — cn utility, icon runtime, Tailwind v4 preset, and the vegastack-design CLI (tokens ship separately as @vegastack/design-tokens)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -8,6 +8,9 @@
|
|
|
8
8
|
"url": "git+https://github.com/VegaStack/vegastack-design.git",
|
|
9
9
|
"directory": "packages/design"
|
|
10
10
|
},
|
|
11
|
+
"engines": {
|
|
12
|
+
"node": ">=24.14.0"
|
|
13
|
+
},
|
|
11
14
|
"type": "module",
|
|
12
15
|
"sideEffects": [
|
|
13
16
|
"**/*.css"
|
|
@@ -16,6 +19,7 @@
|
|
|
16
19
|
"dist",
|
|
17
20
|
"bin",
|
|
18
21
|
"css",
|
|
22
|
+
"skills",
|
|
19
23
|
"preset.css"
|
|
20
24
|
],
|
|
21
25
|
"bin": {
|
|
@@ -24,39 +28,56 @@
|
|
|
24
28
|
"exports": {
|
|
25
29
|
".": {
|
|
26
30
|
"types": "./dist/index.d.ts",
|
|
27
|
-
"import": "./dist/index.js"
|
|
31
|
+
"import": "./dist/index.js",
|
|
32
|
+
"require": "./dist/index.cjs",
|
|
33
|
+
"default": "./dist/index.js"
|
|
28
34
|
},
|
|
29
35
|
"./icons": {
|
|
30
36
|
"types": "./dist/icons/index.d.ts",
|
|
31
|
-
"import": "./dist/icons/index.js"
|
|
37
|
+
"import": "./dist/icons/index.js",
|
|
38
|
+
"require": "./dist/icons/index.cjs",
|
|
39
|
+
"default": "./dist/icons/index.js"
|
|
40
|
+
},
|
|
41
|
+
"./theme-scope": {
|
|
42
|
+
"types": "./dist/theme-scope.d.ts",
|
|
43
|
+
"import": "./dist/theme-scope.js",
|
|
44
|
+
"require": "./dist/theme-scope.cjs",
|
|
45
|
+
"default": "./dist/theme-scope.js"
|
|
32
46
|
},
|
|
33
47
|
"./preset": {
|
|
34
48
|
"types": "./dist/preset.d.ts",
|
|
35
|
-
"import": "./dist/preset.js"
|
|
49
|
+
"import": "./dist/preset.js",
|
|
50
|
+
"require": "./dist/preset.cjs",
|
|
51
|
+
"default": "./dist/preset.js"
|
|
36
52
|
},
|
|
37
53
|
"./preset.css": "./preset.css",
|
|
38
54
|
"./theme.css": "./css/theme.css",
|
|
39
55
|
"./base.css": "./css/base.css",
|
|
40
|
-
"./utilities.css": "./css/utilities.css"
|
|
56
|
+
"./utilities.css": "./css/utilities.css",
|
|
57
|
+
"./package.json": "./package.json"
|
|
41
58
|
},
|
|
42
59
|
"dependencies": {
|
|
43
60
|
"clsx": "^2.1.1",
|
|
44
|
-
"lucide-react": "^1.24.0",
|
|
45
61
|
"tailwind-merge": "^3.6.0",
|
|
46
|
-
"
|
|
47
|
-
"
|
|
62
|
+
"tsconfig-paths": "^4.2.0",
|
|
63
|
+
"tw-animate-css": "^1.4.0",
|
|
64
|
+
"@vegastack/design-tokens": "^0.2.0"
|
|
48
65
|
},
|
|
49
66
|
"peerDependencies": {
|
|
50
67
|
"react": "^19.0.0",
|
|
51
68
|
"react-dom": "^19.0.0",
|
|
52
|
-
"
|
|
53
|
-
"
|
|
69
|
+
"lucide-react": "^1.24.0",
|
|
70
|
+
"thesvg": "^3.2.6",
|
|
71
|
+
"tailwindcss": "^4.3.2"
|
|
54
72
|
},
|
|
55
73
|
"peerDependenciesMeta": {
|
|
56
74
|
"tailwindcss": {
|
|
57
75
|
"optional": true
|
|
58
76
|
},
|
|
59
|
-
"
|
|
77
|
+
"lucide-react": {
|
|
78
|
+
"optional": true
|
|
79
|
+
},
|
|
80
|
+
"thesvg": {
|
|
60
81
|
"optional": true
|
|
61
82
|
}
|
|
62
83
|
},
|
|
@@ -66,23 +87,24 @@
|
|
|
66
87
|
"@types/react": "^19.2.17",
|
|
67
88
|
"@types/react-dom": "^19.2.3",
|
|
68
89
|
"eslint": "^10.7.0",
|
|
69
|
-
"react": "^
|
|
70
|
-
"react
|
|
90
|
+
"lucide-react": "^1.24.0",
|
|
91
|
+
"react": "^19.2.8",
|
|
92
|
+
"react-dom": "^19.2.8",
|
|
71
93
|
"tailwindcss": "^4.3.2",
|
|
94
|
+
"thesvg": "^3.2.6",
|
|
72
95
|
"tw-animate-css": "^1.4.0",
|
|
73
96
|
"typescript": "^6.0.3",
|
|
74
|
-
"@vegastack/
|
|
75
|
-
"@vegastack/
|
|
97
|
+
"@vegastack/eslint-config": "0.0.0",
|
|
98
|
+
"@vegastack/typescript-config": "0.0.0"
|
|
76
99
|
},
|
|
77
100
|
"publishConfig": {
|
|
78
|
-
"access": "public"
|
|
79
|
-
"provenance": true
|
|
101
|
+
"access": "public"
|
|
80
102
|
},
|
|
81
103
|
"scripts": {
|
|
82
104
|
"build": "tsup",
|
|
83
105
|
"lint": "eslint . && pnpm run verify",
|
|
84
106
|
"verify": "node ../../tooling/verify-preset-source.mjs",
|
|
85
107
|
"typecheck": "tsc --noEmit",
|
|
86
|
-
"test": "node test/compare.test.mjs && node test/check-updates.test.mjs"
|
|
108
|
+
"test": "node test/compare.test.mjs && node test/check-updates.test.mjs && node test/skills-install.test.mjs"
|
|
87
109
|
}
|
|
88
110
|
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: vegastack-brand
|
|
3
|
+
description: VegaStack marketing and external visual identity — logo usage, brand colour, and marketing typography, distinct from the product design system. Currently a deliberate stub with no assets. Use when asked about VegaStack branding, logo usage, marketing colours, or external-facing visual identity.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# VegaStack brand
|
|
7
|
+
|
|
8
|
+
**This skill is a deliberate stub.** Marketing has not yet provided the brand assets (logo,
|
|
9
|
+
marketing palette, marketing typography), so there is nothing here to apply yet.
|
|
10
|
+
|
|
11
|
+
## What to do today
|
|
12
|
+
|
|
13
|
+
For product UI, use the `vegastack-design-system` skill. Its OKLCH semantic tokens are the only
|
|
14
|
+
locked visual identity VegaStack currently has.
|
|
15
|
+
|
|
16
|
+
**Do not invent a marketing palette, logo treatment, or brand typography.** If a task needs one, say
|
|
17
|
+
that the brand layer is not defined yet and ask, rather than generating something plausible that
|
|
18
|
+
will later conflict with the real assets.
|
|
19
|
+
|
|
20
|
+
Brand marks for external and marketing surfaces are rendered through `BrandIcon` from
|
|
21
|
+
`@vegastack/design/icons` (backed by `thesvg`), which is available now.
|
|
22
|
+
|
|
23
|
+
## Scope once populated
|
|
24
|
+
|
|
25
|
+
- Logo usage: variants, clear-space, minimum sizes, prohibited treatments.
|
|
26
|
+
- Brand colour and marketing typography — a separate layer from the product tokens, never a
|
|
27
|
+
replacement for them.
|
|
28
|
+
- Marketing surface patterns, which in the component library are scoped to `.vs-marketing` and must
|
|
29
|
+
never appear in product UI.
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: vegastack-consume
|
|
3
|
+
description: Set up a project to consume the VegaStack design system — install the public npm layer, wire the Tailwind v4 CSS and the provider, configure registry access, add components through the fail-closed integrity flow, override tokens, and keep copies up to date. Use when initialising a new project on VegaStack, adding the first component, fixing setup or registry-auth problems, or wiring the provider.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Consume VegaStack
|
|
7
|
+
|
|
8
|
+
Once setup is done, use the `vegastack-design-system` skill for day-to-day UI work.
|
|
9
|
+
|
|
10
|
+
## 1. Install the public layer
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm i @vegastack/design
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
No credentials needed. It pulls in `@vegastack/design-tokens` as a dependency and provides `cn()`,
|
|
17
|
+
the icon runtime, the Tailwind v4 preset, and the `vegastack-design` CLI.
|
|
18
|
+
|
|
19
|
+
**Invoking the CLI.** The bin is `vegastack-design` but the package is `@vegastack/design`, so a
|
|
20
|
+
bare `npx vegastack-design …` in a project that does not already have it installed would try to
|
|
21
|
+
fetch an unrelated, unscoped package from npm. Use one of these instead — the first once it is a
|
|
22
|
+
local dependency (it resolves from `node_modules` and never contacts the registry), the second for a
|
|
23
|
+
standalone one-off:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
pnpm exec vegastack-design <command>
|
|
27
|
+
npx --package=@vegastack/design vegastack-design <command>
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
`@vegastack/ui` is private and is never installed downstream — components arrive by copy-in.
|
|
31
|
+
|
|
32
|
+
## 2. Tailwind v4 CSS
|
|
33
|
+
|
|
34
|
+
You must be on Tailwind v4.
|
|
35
|
+
|
|
36
|
+
```css
|
|
37
|
+
@import "tailwindcss";
|
|
38
|
+
@import "@vegastack/design/theme.css"; /* :root + .dark + the @theme inline bridge */
|
|
39
|
+
@import "@vegastack/design/base.css"; /* border-border, body bg, :focus-visible, pointer cursor
|
|
40
|
+
on interactive controls, reduced-motion, and
|
|
41
|
+
body { isolation: isolate } — see step 3 */
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Or one import that bundles all of it plus tw-animate:
|
|
45
|
+
|
|
46
|
+
```css
|
|
47
|
+
@import "@vegastack/design/preset.css";
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**No manual `@source` is required.** The preset already declares `@source` for the classes that live
|
|
51
|
+
inside the published builds — the icon runtime, and the provider/Toaster classNames (sonner emits
|
|
52
|
+
`group-[.toaster]:bg-popover`-style classes that Tailwind must be told to generate). Your own
|
|
53
|
+
application and component source is scanned by Tailwind as usual.
|
|
54
|
+
|
|
55
|
+
## 3. Wrap the app root in the provider
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
npx shadcn@latest add @vegastack/provider
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
This copies `VegaStackProvider` and `useVegaStackTheme` into your project, composing the `sonner`
|
|
62
|
+
Toaster item.
|
|
63
|
+
|
|
64
|
+
```tsx
|
|
65
|
+
import { VegaStackProvider } from "@/components/ui/provider";
|
|
66
|
+
|
|
67
|
+
// <html suppressHydrationWarning> — next-themes mutates it
|
|
68
|
+
<body className="isolate">
|
|
69
|
+
<VegaStackProvider>{children}</VegaStackProvider>
|
|
70
|
+
</body>;
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
It bundles theme (next-themes, class-based dark), the Sonner toaster, and the Base UI tooltip and
|
|
74
|
+
direction providers.
|
|
75
|
+
|
|
76
|
+
**The `isolate` is required, not cosmetic.** Overlay components (Dialog, Sheet, Popover, Tooltip,
|
|
77
|
+
Select, menus) portal to `<body>` and depend on a root stacking context to render above page
|
|
78
|
+
content. Get it from `@vegastack/design/base.css` (which sets `body { isolation: isolate }`) or by
|
|
79
|
+
putting `className="isolate"` on your `<body>` yourself. Without it, popups can render _under_ app
|
|
80
|
+
chrome or mis-position in stacking-context-heavy layouts.
|
|
81
|
+
|
|
82
|
+
## 4. Configure registry access
|
|
83
|
+
|
|
84
|
+
Components come from a private registry behind Cloudflare Access service tokens.
|
|
85
|
+
|
|
86
|
+
If the project has no `components.json` yet, create one first — pick the **base** style, never
|
|
87
|
+
`radix`, because VegaStack components are Base UI:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
pnpm dlx shadcn@latest init --base base
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Then add the registry block to `components.json`:
|
|
94
|
+
|
|
95
|
+
```json
|
|
96
|
+
{
|
|
97
|
+
"registries": {
|
|
98
|
+
"@vegastack": {
|
|
99
|
+
"url": "https://design.vegastack.com/r/{name}.json",
|
|
100
|
+
"headers": {
|
|
101
|
+
"CF-Access-Client-Id": "${CF_ACCESS_CLIENT_ID}",
|
|
102
|
+
"CF-Access-Client-Secret": "${CF_ACCESS_CLIENT_SECRET}"
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Put the credentials in `.env.local`. Inspect before writing anything:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
pnpm dlx shadcn@latest add @vegastack/button --dry-run
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
External and client projects are **tokenless** — components are copied in during development, and
|
|
116
|
+
the shipped application holds zero VegaStack credentials.
|
|
117
|
+
|
|
118
|
+
## 5. Add a component (fail-closed, three steps)
|
|
119
|
+
|
|
120
|
+
This is the only safe way to add a component. Do not collapse it to a bare `shadcn add`: that leaves
|
|
121
|
+
a time-of-check/time-of-use gap, because `shadcn add` re-fetches the item after any preflight.
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
# Create a private directory and choose a NEW file path inside it. The verifier refuses an
|
|
125
|
+
# existing path or a symlink rather than overwriting or following it.
|
|
126
|
+
DIR="$(mktemp -d "${TMPDIR:-/tmp}/vegastack-verify.XXXXXX")"; ITEM="$DIR/button.json"
|
|
127
|
+
|
|
128
|
+
# 1) PRE-WRITE — verify signature + hash, and save the trusted bytes for step 3.
|
|
129
|
+
npx --package=@vegastack/design vegastack-design verify --save "$ITEM" button
|
|
130
|
+
|
|
131
|
+
# Retain the verified digest in the parent shell BEFORE shadcn or dependency code runs.
|
|
132
|
+
EXPECTED="$(node -e 'process.stdout.write(JSON.parse(require("node:fs").readFileSync(process.argv[1],"utf8")).meta.integrity)' "$ITEM")"
|
|
133
|
+
|
|
134
|
+
# 2) COPY-IN — shadcn writes the files, rewriting import aliases per your components.json.
|
|
135
|
+
pnpm dlx shadcn@latest add @vegastack/button
|
|
136
|
+
|
|
137
|
+
# 3) POST-WRITE — prove the copied files match the SAVED item. Exits 1 on any tampering.
|
|
138
|
+
npx --package=@vegastack/design vegastack-design verify \
|
|
139
|
+
--post-write --item "$ITEM" --expected-integrity "$EXPECTED" --target-dir .
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Add `--hash-only` to step 1 only for local development or before the signed manifest is deployed —
|
|
143
|
+
it skips `cosign` and therefore does **not** prove provenance.
|
|
144
|
+
|
|
145
|
+
What each step guarantees, what it deliberately does not, and every flag and environment variable:
|
|
146
|
+
[references/registry-integrity.md](references/registry-integrity.md).
|
|
147
|
+
|
|
148
|
+
## 6. Override tokens
|
|
149
|
+
|
|
150
|
+
One file, one variable, and every component repaints in both themes:
|
|
151
|
+
|
|
152
|
+
```css
|
|
153
|
+
:root {
|
|
154
|
+
--primary: oklch(0.55 0.2 264);
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Never override a `--color-*` variable — that is the build-inlined bridge, not the runtime contract.
|
|
159
|
+
|
|
160
|
+
## 7. Stay current
|
|
161
|
+
|
|
162
|
+
Copy-in means no automatic updates.
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
npx --package=@vegastack/design vegastack-design check-updates # ⬆ update · ≈ drift · ✓ up to date
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Then per stale component: `shadcn add @vegastack/<name> --diff` to review, `--overwrite` to apply,
|
|
169
|
+
and re-run the step-3 post-write verification. Details and CI wiring:
|
|
170
|
+
[references/registry-integrity.md](references/registry-integrity.md).
|
|
171
|
+
|
|
172
|
+
Add the Renovate preset `github>VegaStack/renovate-config` so additive token bumps arrive as PRs.
|
|
173
|
+
|
|
174
|
+
## Install the agent skills
|
|
175
|
+
|
|
176
|
+
If this project's agents do not already have them:
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
npx --package=@vegastack/design vegastack-design skills install
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Writes the public VegaStack skills into `.claude/skills/` and `.agents/skills/`.
|