@ttoss/fsl-ui 0.2.5 → 0.2.7
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 +1 -1
- package/dist/components/AppShell/AppShell.cjs +8 -4
- package/dist/components/AppShell/AppShell.mjs +8 -4
- package/dist/components/Container/Container.cjs +2 -1
- package/dist/components/Container/Container.mjs +2 -1
- package/dist/components/Grid/Grid.cjs +20 -1
- package/dist/components/Grid/Grid.d.cts +5 -0
- package/dist/components/Grid/Grid.d.mts +5 -0
- package/dist/components/Grid/Grid.mjs +18 -1
- package/dist/components/Icon/Icon.cjs +2 -1
- package/dist/components/Icon/Icon.d.cts +59 -0
- package/dist/components/Icon/Icon.d.mts +59 -0
- package/dist/components/Icon/Icon.mjs +1 -1
- package/dist/components/Icon/glyphs.cjs +37 -10
- package/dist/components/Icon/glyphs.mjs +34 -10
- package/dist/components/Icon/intents.cjs +32 -0
- package/dist/components/Icon/intents.d.cts +33 -0
- package/dist/components/Icon/intents.d.mts +33 -0
- package/dist/components/Icon/intents.mjs +32 -0
- package/dist/components/Table/Table.cjs +248 -0
- package/dist/components/Table/Table.d.cts +128 -0
- package/dist/components/Table/Table.d.mts +128 -0
- package/dist/components/Table/Table.mjs +239 -0
- package/dist/components/Tabs/Tabs.cjs +70 -27
- package/dist/components/Tabs/Tabs.d.cts +0 -17
- package/dist/components/Tabs/Tabs.d.mts +0 -17
- package/dist/components/Tabs/Tabs.mjs +68 -27
- package/dist/components/Text/Text.cjs +1 -0
- package/dist/components/Text/Text.d.cts +7 -2
- package/dist/components/Text/Text.d.mts +7 -2
- package/dist/components/Text/Text.mjs +1 -0
- package/dist/index.cjs +16 -0
- package/dist/index.d.cts +4 -1
- package/dist/index.d.mts +4 -1
- package/dist/index.mjs +4 -1
- package/llms.txt +45 -9
- package/package.json +4 -4
- package/src/tokens/CONTRACT.md +5 -6
package/README.md
CHANGED
|
@@ -59,7 +59,7 @@ Composites accept no `style`/`className`. Geometry the host legitimately owns is
|
|
|
59
59
|
|
|
60
60
|
The registered knobs and the full policy live in `src/tokens/CONTRACT.md` §7.
|
|
61
61
|
|
|
62
|
-
Icons are
|
|
62
|
+
Icons are semantic: `Icon` (public since ADR-010) is named by intent (`<Icon intent="status.success" />`), never by glyph. The theme maps intents to [Iconify](https://iconify.design/) glyphs (default set: Lucide), registered offline (no runtime network fetch); color inherits via `currentColor` and size comes from `vars.sizing.icon.*`.
|
|
63
63
|
|
|
64
64
|
## AI-first surface
|
|
65
65
|
|
|
@@ -71,7 +71,8 @@ var AppShell = ({
|
|
|
71
71
|
"data-scope": "app-shell",
|
|
72
72
|
"data-part": "header",
|
|
73
73
|
style: {
|
|
74
|
-
borderBlockEnd: HAIRLINE
|
|
74
|
+
borderBlockEnd: HAIRLINE,
|
|
75
|
+
containerType: "inline-size"
|
|
75
76
|
},
|
|
76
77
|
children: header
|
|
77
78
|
}) : null, /* @__PURE__ */(0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -93,7 +94,8 @@ var AppShell = ({
|
|
|
93
94
|
"aria-label": sidebarLabel,
|
|
94
95
|
style: {
|
|
95
96
|
overflowY: "auto",
|
|
96
|
-
borderInlineEnd: HAIRLINE
|
|
97
|
+
borderInlineEnd: HAIRLINE,
|
|
98
|
+
containerType: "inline-size"
|
|
97
99
|
},
|
|
98
100
|
children: sidebar
|
|
99
101
|
}) : null, /* @__PURE__ */(0, react_jsx_runtime.jsx)("main", {
|
|
@@ -101,7 +103,8 @@ var AppShell = ({
|
|
|
101
103
|
"data-part": "main",
|
|
102
104
|
style: {
|
|
103
105
|
overflow: "auto",
|
|
104
|
-
minInlineSize: 0
|
|
106
|
+
minInlineSize: 0,
|
|
107
|
+
containerType: "inline-size"
|
|
105
108
|
},
|
|
106
109
|
children
|
|
107
110
|
}), hasAside ? /* @__PURE__ */(0, react_jsx_runtime.jsx)("aside", {
|
|
@@ -110,7 +113,8 @@ var AppShell = ({
|
|
|
110
113
|
"aria-label": asideLabel,
|
|
111
114
|
style: {
|
|
112
115
|
overflowY: "auto",
|
|
113
|
-
borderInlineStart: HAIRLINE
|
|
116
|
+
borderInlineStart: HAIRLINE,
|
|
117
|
+
containerType: "inline-size"
|
|
114
118
|
},
|
|
115
119
|
children: aside
|
|
116
120
|
}) : null]
|
|
@@ -71,7 +71,8 @@ var AppShell = ({
|
|
|
71
71
|
"data-scope": "app-shell",
|
|
72
72
|
"data-part": "header",
|
|
73
73
|
style: {
|
|
74
|
-
borderBlockEnd: HAIRLINE
|
|
74
|
+
borderBlockEnd: HAIRLINE,
|
|
75
|
+
containerType: "inline-size"
|
|
75
76
|
},
|
|
76
77
|
children: header
|
|
77
78
|
}) : null, /* @__PURE__ */jsxs("div", {
|
|
@@ -93,7 +94,8 @@ var AppShell = ({
|
|
|
93
94
|
"aria-label": sidebarLabel,
|
|
94
95
|
style: {
|
|
95
96
|
overflowY: "auto",
|
|
96
|
-
borderInlineEnd: HAIRLINE
|
|
97
|
+
borderInlineEnd: HAIRLINE,
|
|
98
|
+
containerType: "inline-size"
|
|
97
99
|
},
|
|
98
100
|
children: sidebar
|
|
99
101
|
}) : null, /* @__PURE__ */jsx("main", {
|
|
@@ -101,7 +103,8 @@ var AppShell = ({
|
|
|
101
103
|
"data-part": "main",
|
|
102
104
|
style: {
|
|
103
105
|
overflow: "auto",
|
|
104
|
-
minInlineSize: 0
|
|
106
|
+
minInlineSize: 0,
|
|
107
|
+
containerType: "inline-size"
|
|
105
108
|
},
|
|
106
109
|
children
|
|
107
110
|
}), hasAside ? /* @__PURE__ */jsx("aside", {
|
|
@@ -110,7 +113,8 @@ var AppShell = ({
|
|
|
110
113
|
"aria-label": asideLabel,
|
|
111
114
|
style: {
|
|
112
115
|
overflowY: "auto",
|
|
113
|
-
borderInlineStart: HAIRLINE
|
|
116
|
+
borderInlineStart: HAIRLINE,
|
|
117
|
+
containerType: "inline-size"
|
|
114
118
|
},
|
|
115
119
|
children: aside
|
|
116
120
|
}) : null]
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
/** Powered by @ttoss/config. https://ttoss.dev/docs/modules/packages/config/ */
|
|
2
|
+
const require_runtime = require('../../_virtual/_rolldown/runtime.cjs');
|
|
2
3
|
let _ttoss_fsl_theme_vars = require("@ttoss/fsl-theme/vars");
|
|
3
4
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
5
|
+
let react = require("react");
|
|
6
|
+
react = require_runtime.__toESM(react);
|
|
4
7
|
|
|
5
8
|
//#region src/components/Grid/Grid.tsx
|
|
6
9
|
/** Formal semantic identity — Grid root (Structure entity, 2D layout). */
|
|
@@ -45,6 +48,11 @@ var autoTracks = min => {
|
|
|
45
48
|
* named scale, so grid rhythm stays consistent across a product. For a single
|
|
46
49
|
* axis of flow, reach for `Stack` instead.
|
|
47
50
|
*
|
|
51
|
+
* Each child is hosted in a `data-part="item"` wrapper that establishes
|
|
52
|
+
* `container-type: inline-size` (ADR-011): the theme's container-fluid
|
|
53
|
+
* scales (`cqi` clamps) resolve against the item's track width, so type and
|
|
54
|
+
* spacing inside a narrow tile scale down instead of overflowing.
|
|
55
|
+
*
|
|
48
56
|
* @example
|
|
49
57
|
* ```tsx
|
|
50
58
|
* // Fixed columns
|
|
@@ -78,7 +86,18 @@ var Grid = ({
|
|
|
78
86
|
alignItems: ALIGN[align],
|
|
79
87
|
justifyItems: ALIGN[justify]
|
|
80
88
|
},
|
|
81
|
-
children
|
|
89
|
+
children: react.Children.map(children, child => {
|
|
90
|
+
if (child === null || child === void 0) return child;
|
|
91
|
+
return /* @__PURE__ */(0, react_jsx_runtime.jsx)("div", {
|
|
92
|
+
"data-scope": "grid",
|
|
93
|
+
"data-part": "item",
|
|
94
|
+
style: {
|
|
95
|
+
display: "grid",
|
|
96
|
+
containerType: "inline-size"
|
|
97
|
+
},
|
|
98
|
+
children: child
|
|
99
|
+
});
|
|
100
|
+
})
|
|
82
101
|
});
|
|
83
102
|
};
|
|
84
103
|
Grid.displayName = gridMeta.displayName;
|
|
@@ -62,6 +62,11 @@ interface GridProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'style' |
|
|
|
62
62
|
* named scale, so grid rhythm stays consistent across a product. For a single
|
|
63
63
|
* axis of flow, reach for `Stack` instead.
|
|
64
64
|
*
|
|
65
|
+
* Each child is hosted in a `data-part="item"` wrapper that establishes
|
|
66
|
+
* `container-type: inline-size` (ADR-011): the theme's container-fluid
|
|
67
|
+
* scales (`cqi` clamps) resolve against the item's track width, so type and
|
|
68
|
+
* spacing inside a narrow tile scale down instead of overflowing.
|
|
69
|
+
*
|
|
65
70
|
* @example
|
|
66
71
|
* ```tsx
|
|
67
72
|
* // Fixed columns
|
|
@@ -62,6 +62,11 @@ interface GridProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'style' |
|
|
|
62
62
|
* named scale, so grid rhythm stays consistent across a product. For a single
|
|
63
63
|
* axis of flow, reach for `Stack` instead.
|
|
64
64
|
*
|
|
65
|
+
* Each child is hosted in a `data-part="item"` wrapper that establishes
|
|
66
|
+
* `container-type: inline-size` (ADR-011): the theme's container-fluid
|
|
67
|
+
* scales (`cqi` clamps) resolve against the item's track width, so type and
|
|
68
|
+
* spacing inside a narrow tile scale down instead of overflowing.
|
|
69
|
+
*
|
|
65
70
|
* @example
|
|
66
71
|
* ```tsx
|
|
67
72
|
* // Fixed columns
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/** Powered by @ttoss/config. https://ttoss.dev/docs/modules/packages/config/ */
|
|
2
2
|
import { vars } from "@ttoss/fsl-theme/vars";
|
|
3
3
|
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
import * as React from "react";
|
|
4
5
|
|
|
5
6
|
//#region src/components/Grid/Grid.tsx
|
|
6
7
|
/** Formal semantic identity — Grid root (Structure entity, 2D layout). */
|
|
@@ -45,6 +46,11 @@ var autoTracks = min => {
|
|
|
45
46
|
* named scale, so grid rhythm stays consistent across a product. For a single
|
|
46
47
|
* axis of flow, reach for `Stack` instead.
|
|
47
48
|
*
|
|
49
|
+
* Each child is hosted in a `data-part="item"` wrapper that establishes
|
|
50
|
+
* `container-type: inline-size` (ADR-011): the theme's container-fluid
|
|
51
|
+
* scales (`cqi` clamps) resolve against the item's track width, so type and
|
|
52
|
+
* spacing inside a narrow tile scale down instead of overflowing.
|
|
53
|
+
*
|
|
48
54
|
* @example
|
|
49
55
|
* ```tsx
|
|
50
56
|
* // Fixed columns
|
|
@@ -78,7 +84,18 @@ var Grid = ({
|
|
|
78
84
|
alignItems: ALIGN[align],
|
|
79
85
|
justifyItems: ALIGN[justify]
|
|
80
86
|
},
|
|
81
|
-
children
|
|
87
|
+
children: React.Children.map(children, child => {
|
|
88
|
+
if (child === null || child === void 0) return child;
|
|
89
|
+
return /* @__PURE__ */jsx("div", {
|
|
90
|
+
"data-scope": "grid",
|
|
91
|
+
"data-part": "item",
|
|
92
|
+
style: {
|
|
93
|
+
display: "grid",
|
|
94
|
+
containerType: "inline-size"
|
|
95
|
+
},
|
|
96
|
+
children: child
|
|
97
|
+
});
|
|
98
|
+
})
|
|
82
99
|
});
|
|
83
100
|
};
|
|
84
101
|
Grid.displayName = gridMeta.displayName;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
|
|
2
|
+
import { IconIntent } from "./intents.cjs";
|
|
3
|
+
|
|
4
|
+
//#region src/components/Icon/Icon.d.ts
|
|
5
|
+
/** Formal semantic identity — Icon (Structure entity, static glyph). */
|
|
6
|
+
declare const iconMeta: {
|
|
7
|
+
readonly displayName: "Icon";
|
|
8
|
+
readonly entity: "Structure";
|
|
9
|
+
readonly structure: "icon";
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Icon size step. Maps directly to `vars.sizing.icon.*` — the sizing scale
|
|
13
|
+
* icon-system.md defines as the Icon contract. This is not the density
|
|
14
|
+
* `size` prop CONTRACT.md §4 bans (that rule governs interactive hit
|
|
15
|
+
* targets): a glyph legitimately scales with the context it reinforces.
|
|
16
|
+
*/
|
|
17
|
+
type IconSize = 'sm' | 'md' | 'lg';
|
|
18
|
+
/** Props for the Icon component. */
|
|
19
|
+
interface IconProps {
|
|
20
|
+
/**
|
|
21
|
+
* Semantic intent — what the icon *means* (`icon.{family}.{intent}`), not
|
|
22
|
+
* which glyph renders. The theme maps it to a glyph (default: Lucide).
|
|
23
|
+
*/
|
|
24
|
+
intent: IconIntent;
|
|
25
|
+
/**
|
|
26
|
+
* Size step, mapped to `vars.sizing.icon.{size}`. Defaults to `md`.
|
|
27
|
+
*/
|
|
28
|
+
size?: IconSize;
|
|
29
|
+
/**
|
|
30
|
+
* Accessible label. When omitted the icon is decorative (`aria-hidden`) —
|
|
31
|
+
* the default, since icons here reinforce a labelled host control. Supply
|
|
32
|
+
* a (caller-localized) label only when the icon is the sole carrier of
|
|
33
|
+
* meaning.
|
|
34
|
+
*/
|
|
35
|
+
label?: string;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Renders a semantic glyph via the Iconify provider (ADR-005).
|
|
39
|
+
*
|
|
40
|
+
* Icon is named by intent and inherits its color from context
|
|
41
|
+
* (`currentColor`); only its size is a token. Glyphs are registered offline
|
|
42
|
+
* on first render (`ensureIconGlyphs`), so no network request is made.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```tsx
|
|
46
|
+
* <Icon intent="disclosure.expand" />
|
|
47
|
+
* <Icon intent="action.close" size="sm" label={closeLabel} />
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
declare const Icon: {
|
|
51
|
+
({
|
|
52
|
+
intent,
|
|
53
|
+
size,
|
|
54
|
+
label
|
|
55
|
+
}: IconProps): import("react/jsx-runtime").JSX.Element;
|
|
56
|
+
displayName: "Icon";
|
|
57
|
+
};
|
|
58
|
+
//#endregion
|
|
59
|
+
export { Icon, IconProps, IconSize, iconMeta };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
|
|
2
|
+
import { IconIntent } from "./intents.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/components/Icon/Icon.d.ts
|
|
5
|
+
/** Formal semantic identity — Icon (Structure entity, static glyph). */
|
|
6
|
+
declare const iconMeta: {
|
|
7
|
+
readonly displayName: "Icon";
|
|
8
|
+
readonly entity: "Structure";
|
|
9
|
+
readonly structure: "icon";
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Icon size step. Maps directly to `vars.sizing.icon.*` — the sizing scale
|
|
13
|
+
* icon-system.md defines as the Icon contract. This is not the density
|
|
14
|
+
* `size` prop CONTRACT.md §4 bans (that rule governs interactive hit
|
|
15
|
+
* targets): a glyph legitimately scales with the context it reinforces.
|
|
16
|
+
*/
|
|
17
|
+
type IconSize = 'sm' | 'md' | 'lg';
|
|
18
|
+
/** Props for the Icon component. */
|
|
19
|
+
interface IconProps {
|
|
20
|
+
/**
|
|
21
|
+
* Semantic intent — what the icon *means* (`icon.{family}.{intent}`), not
|
|
22
|
+
* which glyph renders. The theme maps it to a glyph (default: Lucide).
|
|
23
|
+
*/
|
|
24
|
+
intent: IconIntent;
|
|
25
|
+
/**
|
|
26
|
+
* Size step, mapped to `vars.sizing.icon.{size}`. Defaults to `md`.
|
|
27
|
+
*/
|
|
28
|
+
size?: IconSize;
|
|
29
|
+
/**
|
|
30
|
+
* Accessible label. When omitted the icon is decorative (`aria-hidden`) —
|
|
31
|
+
* the default, since icons here reinforce a labelled host control. Supply
|
|
32
|
+
* a (caller-localized) label only when the icon is the sole carrier of
|
|
33
|
+
* meaning.
|
|
34
|
+
*/
|
|
35
|
+
label?: string;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Renders a semantic glyph via the Iconify provider (ADR-005).
|
|
39
|
+
*
|
|
40
|
+
* Icon is named by intent and inherits its color from context
|
|
41
|
+
* (`currentColor`); only its size is a token. Glyphs are registered offline
|
|
42
|
+
* on first render (`ensureIconGlyphs`), so no network request is made.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```tsx
|
|
46
|
+
* <Icon intent="disclosure.expand" />
|
|
47
|
+
* <Icon intent="action.close" size="sm" label={closeLabel} />
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
declare const Icon: {
|
|
51
|
+
({
|
|
52
|
+
intent,
|
|
53
|
+
size,
|
|
54
|
+
label
|
|
55
|
+
}: IconProps): import("react/jsx-runtime").JSX.Element;
|
|
56
|
+
displayName: "Icon";
|
|
57
|
+
};
|
|
58
|
+
//#endregion
|
|
59
|
+
export { Icon, IconProps, IconSize, iconMeta };
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
/** Powered by @ttoss/config. https://ttoss.dev/docs/modules/packages/config/ */
|
|
2
2
|
const require_runtime = require('../../_virtual/_rolldown/runtime.cjs');
|
|
3
3
|
let _iconify_icon_react = require("@iconify-icon/react");
|
|
4
|
+
let _iconify_icons_lucide_arrow_down_wide_narrow_js = require("@iconify/icons-lucide/arrow-down-wide-narrow.js");
|
|
5
|
+
_iconify_icons_lucide_arrow_down_wide_narrow_js = require_runtime.__toESM(_iconify_icons_lucide_arrow_down_wide_narrow_js, 1);
|
|
6
|
+
let _iconify_icons_lucide_arrow_up_narrow_wide_js = require("@iconify/icons-lucide/arrow-up-narrow-wide.js");
|
|
7
|
+
_iconify_icons_lucide_arrow_up_narrow_wide_js = require_runtime.__toESM(_iconify_icons_lucide_arrow_up_narrow_wide_js, 1);
|
|
4
8
|
let _iconify_icons_lucide_check_js = require("@iconify/icons-lucide/check.js");
|
|
5
9
|
_iconify_icons_lucide_check_js = require_runtime.__toESM(_iconify_icons_lucide_check_js, 1);
|
|
10
|
+
let _iconify_icons_lucide_check_circle_2_js = require("@iconify/icons-lucide/check-circle-2.js");
|
|
11
|
+
_iconify_icons_lucide_check_circle_2_js = require_runtime.__toESM(_iconify_icons_lucide_check_circle_2_js, 1);
|
|
6
12
|
let _iconify_icons_lucide_chevron_down_js = require("@iconify/icons-lucide/chevron-down.js");
|
|
7
13
|
_iconify_icons_lucide_chevron_down_js = require_runtime.__toESM(_iconify_icons_lucide_chevron_down_js, 1);
|
|
8
14
|
let _iconify_icons_lucide_chevron_right_js = require("@iconify/icons-lucide/chevron-right.js");
|
|
@@ -33,18 +39,34 @@ _iconify_icons_lucide_x_js = require_runtime.__toESM(_iconify_icons_lucide_x_js,
|
|
|
33
39
|
* @see ../../../CONTRIBUTING.md ADR-005
|
|
34
40
|
*/
|
|
35
41
|
/**
|
|
42
|
+
* The per-icon lucide modules are CommonJS (`exports.default = data` with
|
|
43
|
+
* `__esModule`). Bundlers disagree on default-import interop: Babel/Jest
|
|
44
|
+
* respect `__esModule` (import = the data), while Node-mode interop
|
|
45
|
+
* (Vite/Rolldown, Node ESM) makes the import the whole `module.exports` —
|
|
46
|
+
* `{ __esModule, default: data }`. Normalize both shapes; without this,
|
|
47
|
+
* `addIcon` receives an invalid payload and rejects it *silently*, every
|
|
48
|
+
* icon falls back to an Iconify API fetch, and no glyph renders in
|
|
49
|
+
* production builds (friction F-012).
|
|
50
|
+
*/
|
|
51
|
+
var unwrapGlyph = mod => {
|
|
52
|
+
return "body" in mod ? mod : mod.default;
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
36
55
|
* The default (Lucide) glyph for every intent. `satisfies Record<…>` makes a
|
|
37
56
|
* missing intent a compile error — the completeness rule from icon-system.md.
|
|
38
57
|
*/
|
|
39
58
|
var INTENT_GLYPHS = {
|
|
40
|
-
"disclosure.expand": _iconify_icons_lucide_chevron_down_js.default,
|
|
41
|
-
"disclosure.collapse": _iconify_icons_lucide_chevron_right_js.default,
|
|
42
|
-
"selection.checked": _iconify_icons_lucide_check_js.default,
|
|
43
|
-
"selection.indeterminate": _iconify_icons_lucide_minus_js.default,
|
|
44
|
-
"action.close": _iconify_icons_lucide_x_js.default,
|
|
45
|
-
"action.search": _iconify_icons_lucide_search_js.default,
|
|
46
|
-
"action.increment": _iconify_icons_lucide_plus_js.default,
|
|
47
|
-
"action.decrement": _iconify_icons_lucide_minus_js.default
|
|
59
|
+
"disclosure.expand": unwrapGlyph(_iconify_icons_lucide_chevron_down_js.default),
|
|
60
|
+
"disclosure.collapse": unwrapGlyph(_iconify_icons_lucide_chevron_right_js.default),
|
|
61
|
+
"selection.checked": unwrapGlyph(_iconify_icons_lucide_check_js.default),
|
|
62
|
+
"selection.indeterminate": unwrapGlyph(_iconify_icons_lucide_minus_js.default),
|
|
63
|
+
"action.close": unwrapGlyph(_iconify_icons_lucide_x_js.default),
|
|
64
|
+
"action.search": unwrapGlyph(_iconify_icons_lucide_search_js.default),
|
|
65
|
+
"action.increment": unwrapGlyph(_iconify_icons_lucide_plus_js.default),
|
|
66
|
+
"action.decrement": unwrapGlyph(_iconify_icons_lucide_minus_js.default),
|
|
67
|
+
"action.sortAscending": unwrapGlyph(_iconify_icons_lucide_arrow_up_narrow_wide_js.default),
|
|
68
|
+
"action.sortDescending": unwrapGlyph(_iconify_icons_lucide_arrow_down_wide_narrow_js.default),
|
|
69
|
+
"status.success": unwrapGlyph(_iconify_icons_lucide_check_circle_2_js.default)
|
|
48
70
|
};
|
|
49
71
|
/**
|
|
50
72
|
* The Iconify registry name for an intent — `fsl-ui:{family}-{intent}`. The
|
|
@@ -52,7 +74,9 @@ var INTENT_GLYPHS = {
|
|
|
52
74
|
* clobbered by) icons an application registers under bare names.
|
|
53
75
|
*/
|
|
54
76
|
var iconifyName = intent => {
|
|
55
|
-
return `fsl-ui:${intent.replace(".", "-")
|
|
77
|
+
return `fsl-ui:${intent.replace(".", "-").replace(/[A-Z]/g, letter => {
|
|
78
|
+
return `-${letter.toLowerCase()}`;
|
|
79
|
+
})}`;
|
|
56
80
|
};
|
|
57
81
|
var registered = false;
|
|
58
82
|
/**
|
|
@@ -63,7 +87,10 @@ var registered = false;
|
|
|
63
87
|
*/
|
|
64
88
|
var ensureIconGlyphs = () => {
|
|
65
89
|
if (registered) return;
|
|
66
|
-
for (const [intent, glyph] of Object.entries(INTENT_GLYPHS))
|
|
90
|
+
for (const [intent, glyph] of Object.entries(INTENT_GLYPHS)) {
|
|
91
|
+
const name = iconifyName(intent);
|
|
92
|
+
if (!(0, _iconify_icon_react.addIcon)(name, glyph)) throw new Error(`fsl-ui Icon: failed to register glyph "${name}" for intent "${intent}" — invalid Iconify name or data.`);
|
|
93
|
+
}
|
|
67
94
|
registered = true;
|
|
68
95
|
};
|
|
69
96
|
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
/** Powered by @ttoss/config. https://ttoss.dev/docs/modules/packages/config/ */
|
|
2
2
|
import { addIcon } from "@iconify-icon/react";
|
|
3
|
+
import arrowDownWideNarrowGlyph from "@iconify/icons-lucide/arrow-down-wide-narrow.js";
|
|
4
|
+
import arrowUpNarrowWideGlyph from "@iconify/icons-lucide/arrow-up-narrow-wide.js";
|
|
3
5
|
import checkGlyph from "@iconify/icons-lucide/check.js";
|
|
6
|
+
import checkCircleGlyph from "@iconify/icons-lucide/check-circle-2.js";
|
|
4
7
|
import chevronDownGlyph from "@iconify/icons-lucide/chevron-down.js";
|
|
5
8
|
import chevronRightGlyph from "@iconify/icons-lucide/chevron-right.js";
|
|
6
9
|
import minusGlyph from "@iconify/icons-lucide/minus.js";
|
|
@@ -25,18 +28,34 @@ import xGlyph from "@iconify/icons-lucide/x.js";
|
|
|
25
28
|
* @see ../../../CONTRIBUTING.md ADR-005
|
|
26
29
|
*/
|
|
27
30
|
/**
|
|
31
|
+
* The per-icon lucide modules are CommonJS (`exports.default = data` with
|
|
32
|
+
* `__esModule`). Bundlers disagree on default-import interop: Babel/Jest
|
|
33
|
+
* respect `__esModule` (import = the data), while Node-mode interop
|
|
34
|
+
* (Vite/Rolldown, Node ESM) makes the import the whole `module.exports` —
|
|
35
|
+
* `{ __esModule, default: data }`. Normalize both shapes; without this,
|
|
36
|
+
* `addIcon` receives an invalid payload and rejects it *silently*, every
|
|
37
|
+
* icon falls back to an Iconify API fetch, and no glyph renders in
|
|
38
|
+
* production builds (friction F-012).
|
|
39
|
+
*/
|
|
40
|
+
var unwrapGlyph = mod => {
|
|
41
|
+
return "body" in mod ? mod : mod.default;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
28
44
|
* The default (Lucide) glyph for every intent. `satisfies Record<…>` makes a
|
|
29
45
|
* missing intent a compile error — the completeness rule from icon-system.md.
|
|
30
46
|
*/
|
|
31
47
|
var INTENT_GLYPHS = {
|
|
32
|
-
"disclosure.expand": chevronDownGlyph,
|
|
33
|
-
"disclosure.collapse": chevronRightGlyph,
|
|
34
|
-
"selection.checked": checkGlyph,
|
|
35
|
-
"selection.indeterminate": minusGlyph,
|
|
36
|
-
"action.close": xGlyph,
|
|
37
|
-
"action.search": searchGlyph,
|
|
38
|
-
"action.increment": plusGlyph,
|
|
39
|
-
"action.decrement": minusGlyph
|
|
48
|
+
"disclosure.expand": unwrapGlyph(chevronDownGlyph),
|
|
49
|
+
"disclosure.collapse": unwrapGlyph(chevronRightGlyph),
|
|
50
|
+
"selection.checked": unwrapGlyph(checkGlyph),
|
|
51
|
+
"selection.indeterminate": unwrapGlyph(minusGlyph),
|
|
52
|
+
"action.close": unwrapGlyph(xGlyph),
|
|
53
|
+
"action.search": unwrapGlyph(searchGlyph),
|
|
54
|
+
"action.increment": unwrapGlyph(plusGlyph),
|
|
55
|
+
"action.decrement": unwrapGlyph(minusGlyph),
|
|
56
|
+
"action.sortAscending": unwrapGlyph(arrowUpNarrowWideGlyph),
|
|
57
|
+
"action.sortDescending": unwrapGlyph(arrowDownWideNarrowGlyph),
|
|
58
|
+
"status.success": unwrapGlyph(checkCircleGlyph)
|
|
40
59
|
};
|
|
41
60
|
/**
|
|
42
61
|
* The Iconify registry name for an intent — `fsl-ui:{family}-{intent}`. The
|
|
@@ -44,7 +63,9 @@ var INTENT_GLYPHS = {
|
|
|
44
63
|
* clobbered by) icons an application registers under bare names.
|
|
45
64
|
*/
|
|
46
65
|
var iconifyName = intent => {
|
|
47
|
-
return `fsl-ui:${intent.replace(".", "-")
|
|
66
|
+
return `fsl-ui:${intent.replace(".", "-").replace(/[A-Z]/g, letter => {
|
|
67
|
+
return `-${letter.toLowerCase()}`;
|
|
68
|
+
})}`;
|
|
48
69
|
};
|
|
49
70
|
var registered = false;
|
|
50
71
|
/**
|
|
@@ -55,7 +76,10 @@ var registered = false;
|
|
|
55
76
|
*/
|
|
56
77
|
var ensureIconGlyphs = () => {
|
|
57
78
|
if (registered) return;
|
|
58
|
-
for (const [intent, glyph] of Object.entries(INTENT_GLYPHS))
|
|
79
|
+
for (const [intent, glyph] of Object.entries(INTENT_GLYPHS)) {
|
|
80
|
+
const name = iconifyName(intent);
|
|
81
|
+
if (!addIcon(name, glyph)) throw new Error(`fsl-ui Icon: failed to register glyph "${name}" for intent "${intent}" — invalid Iconify name or data.`);
|
|
82
|
+
}
|
|
59
83
|
registered = true;
|
|
60
84
|
};
|
|
61
85
|
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/** Powered by @ttoss/config. https://ttoss.dev/docs/modules/packages/config/ */
|
|
2
|
+
//#region src/components/Icon/intents.ts
|
|
3
|
+
/**
|
|
4
|
+
* Icon semantic layer — the intent vocabulary.
|
|
5
|
+
*
|
|
6
|
+
* This is the provider-agnostic contract described by
|
|
7
|
+
* `docs/design/design-system/components/icon-system.md`: an Icon is named by
|
|
8
|
+
* **what it means** (`icon.{family}.{intent}`), never by which glyph or which
|
|
9
|
+
* icon library renders it. The theme (here: the default Lucide mapping in
|
|
10
|
+
* `glyphs.ts`) decides the glyph; this file decides the meanings.
|
|
11
|
+
*
|
|
12
|
+
* Scope (ROADMAP B1): this is intentionally a **subset** of the canonical
|
|
13
|
+
* registry — only the intents that shipped components actually consume today.
|
|
14
|
+
* The registry "grows slowly and shrinks never" (icon-system.md § Change
|
|
15
|
+
* Rules): add an intent here (and its glyph in `glyphs.ts`) when a new
|
|
16
|
+
* component needs one, never speculatively.
|
|
17
|
+
*
|
|
18
|
+
* This module is the seed of the future standalone `@ttoss/fsl-icon` package;
|
|
19
|
+
* it stays free of React and token imports so it can be lifted out whole.
|
|
20
|
+
*
|
|
21
|
+
* @see ../../../CONTRIBUTING.md ADR-005 — Iconify provider + internal intent layer
|
|
22
|
+
* @see docs/design/design-system/components/icon-system.md — full contract
|
|
23
|
+
*/
|
|
24
|
+
/**
|
|
25
|
+
* The intents currently backed by a glyph, grouped by family. Values are the
|
|
26
|
+
* canonical `{family}.{intent}` identifiers. Adding a member here is a
|
|
27
|
+
* type-level requirement to add its glyph in `INTENT_GLYPHS` (`glyphs.ts`).
|
|
28
|
+
*/
|
|
29
|
+
var ICON_INTENTS = ["disclosure.expand", "disclosure.collapse", "selection.checked", "selection.indeterminate", "action.close", "action.search", "action.increment", "action.decrement", "action.sortAscending", "action.sortDescending", "status.success"];
|
|
30
|
+
|
|
31
|
+
//#endregion
|
|
32
|
+
exports.ICON_INTENTS = ICON_INTENTS;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/components/Icon/intents.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* Icon semantic layer — the intent vocabulary.
|
|
5
|
+
*
|
|
6
|
+
* This is the provider-agnostic contract described by
|
|
7
|
+
* `docs/design/design-system/components/icon-system.md`: an Icon is named by
|
|
8
|
+
* **what it means** (`icon.{family}.{intent}`), never by which glyph or which
|
|
9
|
+
* icon library renders it. The theme (here: the default Lucide mapping in
|
|
10
|
+
* `glyphs.ts`) decides the glyph; this file decides the meanings.
|
|
11
|
+
*
|
|
12
|
+
* Scope (ROADMAP B1): this is intentionally a **subset** of the canonical
|
|
13
|
+
* registry — only the intents that shipped components actually consume today.
|
|
14
|
+
* The registry "grows slowly and shrinks never" (icon-system.md § Change
|
|
15
|
+
* Rules): add an intent here (and its glyph in `glyphs.ts`) when a new
|
|
16
|
+
* component needs one, never speculatively.
|
|
17
|
+
*
|
|
18
|
+
* This module is the seed of the future standalone `@ttoss/fsl-icon` package;
|
|
19
|
+
* it stays free of React and token imports so it can be lifted out whole.
|
|
20
|
+
*
|
|
21
|
+
* @see ../../../CONTRIBUTING.md ADR-005 — Iconify provider + internal intent layer
|
|
22
|
+
* @see docs/design/design-system/components/icon-system.md — full contract
|
|
23
|
+
*/
|
|
24
|
+
/**
|
|
25
|
+
* The intents currently backed by a glyph, grouped by family. Values are the
|
|
26
|
+
* canonical `{family}.{intent}` identifiers. Adding a member here is a
|
|
27
|
+
* type-level requirement to add its glyph in `INTENT_GLYPHS` (`glyphs.ts`).
|
|
28
|
+
*/
|
|
29
|
+
declare const ICON_INTENTS: readonly ["disclosure.expand", "disclosure.collapse", "selection.checked", "selection.indeterminate", "action.close", "action.search", "action.increment", "action.decrement", "action.sortAscending", "action.sortDescending", "status.success"];
|
|
30
|
+
/** A semantic icon intent — the public "name" of an icon. */
|
|
31
|
+
type IconIntent = (typeof ICON_INTENTS)[number];
|
|
32
|
+
//#endregion
|
|
33
|
+
export { ICON_INTENTS, IconIntent };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/components/Icon/intents.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* Icon semantic layer — the intent vocabulary.
|
|
5
|
+
*
|
|
6
|
+
* This is the provider-agnostic contract described by
|
|
7
|
+
* `docs/design/design-system/components/icon-system.md`: an Icon is named by
|
|
8
|
+
* **what it means** (`icon.{family}.{intent}`), never by which glyph or which
|
|
9
|
+
* icon library renders it. The theme (here: the default Lucide mapping in
|
|
10
|
+
* `glyphs.ts`) decides the glyph; this file decides the meanings.
|
|
11
|
+
*
|
|
12
|
+
* Scope (ROADMAP B1): this is intentionally a **subset** of the canonical
|
|
13
|
+
* registry — only the intents that shipped components actually consume today.
|
|
14
|
+
* The registry "grows slowly and shrinks never" (icon-system.md § Change
|
|
15
|
+
* Rules): add an intent here (and its glyph in `glyphs.ts`) when a new
|
|
16
|
+
* component needs one, never speculatively.
|
|
17
|
+
*
|
|
18
|
+
* This module is the seed of the future standalone `@ttoss/fsl-icon` package;
|
|
19
|
+
* it stays free of React and token imports so it can be lifted out whole.
|
|
20
|
+
*
|
|
21
|
+
* @see ../../../CONTRIBUTING.md ADR-005 — Iconify provider + internal intent layer
|
|
22
|
+
* @see docs/design/design-system/components/icon-system.md — full contract
|
|
23
|
+
*/
|
|
24
|
+
/**
|
|
25
|
+
* The intents currently backed by a glyph, grouped by family. Values are the
|
|
26
|
+
* canonical `{family}.{intent}` identifiers. Adding a member here is a
|
|
27
|
+
* type-level requirement to add its glyph in `INTENT_GLYPHS` (`glyphs.ts`).
|
|
28
|
+
*/
|
|
29
|
+
declare const ICON_INTENTS: readonly ["disclosure.expand", "disclosure.collapse", "selection.checked", "selection.indeterminate", "action.close", "action.search", "action.increment", "action.decrement", "action.sortAscending", "action.sortDescending", "status.success"];
|
|
30
|
+
/** A semantic icon intent — the public "name" of an icon. */
|
|
31
|
+
type IconIntent = (typeof ICON_INTENTS)[number];
|
|
32
|
+
//#endregion
|
|
33
|
+
export { ICON_INTENTS, IconIntent };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/** Powered by @ttoss/config. https://ttoss.dev/docs/modules/packages/config/ */
|
|
2
|
+
//#region src/components/Icon/intents.ts
|
|
3
|
+
/**
|
|
4
|
+
* Icon semantic layer — the intent vocabulary.
|
|
5
|
+
*
|
|
6
|
+
* This is the provider-agnostic contract described by
|
|
7
|
+
* `docs/design/design-system/components/icon-system.md`: an Icon is named by
|
|
8
|
+
* **what it means** (`icon.{family}.{intent}`), never by which glyph or which
|
|
9
|
+
* icon library renders it. The theme (here: the default Lucide mapping in
|
|
10
|
+
* `glyphs.ts`) decides the glyph; this file decides the meanings.
|
|
11
|
+
*
|
|
12
|
+
* Scope (ROADMAP B1): this is intentionally a **subset** of the canonical
|
|
13
|
+
* registry — only the intents that shipped components actually consume today.
|
|
14
|
+
* The registry "grows slowly and shrinks never" (icon-system.md § Change
|
|
15
|
+
* Rules): add an intent here (and its glyph in `glyphs.ts`) when a new
|
|
16
|
+
* component needs one, never speculatively.
|
|
17
|
+
*
|
|
18
|
+
* This module is the seed of the future standalone `@ttoss/fsl-icon` package;
|
|
19
|
+
* it stays free of React and token imports so it can be lifted out whole.
|
|
20
|
+
*
|
|
21
|
+
* @see ../../../CONTRIBUTING.md ADR-005 — Iconify provider + internal intent layer
|
|
22
|
+
* @see docs/design/design-system/components/icon-system.md — full contract
|
|
23
|
+
*/
|
|
24
|
+
/**
|
|
25
|
+
* The intents currently backed by a glyph, grouped by family. Values are the
|
|
26
|
+
* canonical `{family}.{intent}` identifiers. Adding a member here is a
|
|
27
|
+
* type-level requirement to add its glyph in `INTENT_GLYPHS` (`glyphs.ts`).
|
|
28
|
+
*/
|
|
29
|
+
var ICON_INTENTS = ["disclosure.expand", "disclosure.collapse", "selection.checked", "selection.indeterminate", "action.close", "action.search", "action.increment", "action.decrement", "action.sortAscending", "action.sortDescending", "status.success"];
|
|
30
|
+
|
|
31
|
+
//#endregion
|
|
32
|
+
export { ICON_INTENTS };
|