@godxjp/ui 33.24.0 → 33.25.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/README.md +14 -3
- package/agent/START-HERE.md +5 -5
- package/agent/components/CatalogDetail.json +7 -3
- package/agent/components/DatePicker.json +1 -1
- package/agent/components/DropdownMenu.json +1 -0
- package/agent/components/EditorialCard.json +2 -1
- package/agent/components/Image.json +6 -1
- package/agent/components/Pagination.json +5 -0
- package/agent/components/Popover.json +1 -0
- package/agent/components/Select.json +2 -1
- package/agent/components/Toaster.json +1 -1
- package/agent/components.json +26 -8
- package/agent/index.json +5 -5
- package/agent/llms.txt +6 -6
- package/agent/patterns/notice-bar.json +16 -0
- package/agent/patterns-index.json +15 -0
- package/agent/patterns.json +16 -0
- package/agent/rules.json +2 -2
- package/agent/tokens.json +37 -7
- package/dist/components/charts/chart-cartesian.js +5 -1
- package/dist/components/charts/chart-summary.d.ts +1 -1
- package/dist/components/charts/chart-summary.js +17 -6
- package/dist/components/charts/compact-bar-trend.js +4 -3
- package/dist/components/charts/pie-chart.js +2 -1
- package/dist/components/data-display/image.d.ts +1 -0
- package/dist/components/data-display/image.js +9 -1
- package/dist/components/data-display/popover.js +11 -0
- package/dist/components/data-entry/calendar.js +1 -1
- package/dist/components/data-entry/date-picker.js +22 -5
- package/dist/components/general/button.js +2 -2
- package/dist/components/layout/affix.js +1 -1
- package/dist/components/layout/editorial-catalog.d.ts +1 -1
- package/dist/components/layout/editorial-catalog.js +53 -15
- package/dist/components/navigation/dropdown-menu.d.ts +13 -3
- package/dist/components/navigation/dropdown-menu.js +36 -6
- package/dist/components/navigation/pagination.d.ts +1 -1
- package/dist/components/navigation/pagination.js +13 -1
- package/dist/contracts/measurement.json +1 -1
- package/dist/i18n/messages/en.json +1 -0
- package/dist/i18n/messages/ja.json +1 -0
- package/dist/i18n/messages/vi.json +1 -0
- package/dist/props/components/data-display.prop.d.ts +2 -0
- package/dist/props/components/layout.prop.d.ts +7 -2
- package/dist/props/components/navigation.prop.d.ts +3 -0
- package/dist/props/registry.d.ts +15 -3
- package/dist/props/registry.js +18 -1
- package/dist/styles/application.css +24 -0
- package/dist/styles/base.css +11 -0
- package/dist/styles/control.css +32 -19
- package/dist/styles/core.css +1 -0
- package/dist/styles/data-display-layout.css +7 -0
- package/dist/styles/dialog-layout.css +9 -0
- package/dist/styles/editorial-layout.css +2076 -0
- package/dist/styles/editorial.css +3 -0
- package/dist/styles/index.css +1 -0
- package/dist/styles/layers.json +39 -8
- package/dist/styles/layout.css +0 -1987
- package/dist/styles/precompiled/alert-layout.css +2 -0
- package/dist/styles/precompiled/badge-layout.css +2 -0
- package/dist/styles/precompiled/base.css +2 -0
- package/dist/styles/precompiled/card-layout.css +2 -0
- package/dist/styles/precompiled/chart-layout.css +2 -0
- package/dist/styles/precompiled/control.css +2 -0
- package/dist/styles/precompiled/data-display-layout.css +2 -0
- package/dist/styles/precompiled/data-entry-layout.css +2 -0
- package/dist/styles/precompiled/dialog-layout.css +2 -0
- package/dist/styles/precompiled/editorial-account-layout.css +2 -0
- package/dist/styles/precompiled/editorial-layout.css +2 -0
- package/dist/styles/precompiled/float-button-layout.css +2 -0
- package/dist/styles/precompiled/form-layout.css +2 -0
- package/dist/styles/precompiled/icon-layout.css +2 -0
- package/dist/styles/precompiled/layout.css +2 -0
- package/dist/styles/precompiled/logo-layout.css +2 -0
- package/dist/styles/precompiled/motion.css +2 -0
- package/dist/styles/precompiled/navigation-layout.css +2 -0
- package/dist/styles/precompiled/shell-layout.css +2 -0
- package/dist/styles/precompiled/table-layout.css +2 -0
- package/dist/styles/precompiled/text-layout.css +2 -0
- package/dist/styles/precompiled/toggle.css +2 -0
- package/dist/styles/precompiled/vendor-day-picker.css +2 -0
- package/dist/styles/precompiled/vendor-sonner.css +2 -0
- package/dist/styles.css +1 -1
- package/dist/tokens/components/control.css +3 -0
- package/dist/tokens/components/editorial.css +9 -6
- package/docs/CONSUMER-RULES.md +35 -0
- package/package.json +4 -2
- package/scripts/prune-css.mjs +56 -8
- package/scripts/ui-audit.mjs +36 -0
|
@@ -208,7 +208,7 @@
|
|
|
208
208
|
--editorial-search-border-color: initial;
|
|
209
209
|
|
|
210
210
|
--editorial-search-background: initial;
|
|
211
|
-
--editorial-search-shadow:
|
|
211
|
+
--editorial-search-shadow: initial;
|
|
212
212
|
--editorial-search-icon-size: var(--icon-size-lg);
|
|
213
213
|
|
|
214
214
|
--editorial-search-scope-font-weight: inherit;
|
|
@@ -232,7 +232,7 @@
|
|
|
232
232
|
--editorial-search-popup-max-height: min(32rem, 70vh);
|
|
233
233
|
--editorial-search-popup-padding-block: calc(var(--space-1) + 0.125rem);
|
|
234
234
|
--editorial-search-popup-radius: var(--radius);
|
|
235
|
-
--editorial-search-popup-shadow:
|
|
235
|
+
--editorial-search-popup-shadow: initial;
|
|
236
236
|
|
|
237
237
|
--editorial-search-popup-border-color: initial;
|
|
238
238
|
|
|
@@ -317,7 +317,7 @@
|
|
|
317
317
|
--editorial-showcase-caption-gap: calc(var(--space-3) + 0.0625rem);
|
|
318
318
|
--editorial-showcase-caption-min-width: 16.25rem;
|
|
319
319
|
--editorial-showcase-caption-radius: var(--radius);
|
|
320
|
-
--editorial-showcase-caption-shadow:
|
|
320
|
+
--editorial-showcase-caption-shadow: initial;
|
|
321
321
|
|
|
322
322
|
--editorial-showcase-caption-icon-size: calc(var(--icon-size-xl) + 0.25rem);
|
|
323
323
|
|
|
@@ -365,7 +365,7 @@
|
|
|
365
365
|
--editorial-banner-media-align: start;
|
|
366
366
|
|
|
367
367
|
--editorial-catalog-card-radius: var(--radius);
|
|
368
|
-
--editorial-catalog-card-hover-shadow:
|
|
368
|
+
--editorial-catalog-card-hover-shadow: initial;
|
|
369
369
|
--editorial-catalog-card-hover-translate: -3px;
|
|
370
370
|
--editorial-catalog-card-media-aspect-size: 1 / 1.05;
|
|
371
371
|
--editorial-catalog-card-media-padding-block-start: var(--space-12);
|
|
@@ -450,7 +450,7 @@
|
|
|
450
450
|
--editorial-spotlight-media-inset-block-start: 2rem;
|
|
451
451
|
--editorial-spotlight-media-offset-angle: 12deg;
|
|
452
452
|
--editorial-spotlight-media-shadow: 0 6px 6px rgb(40 25 20 / 0.12);
|
|
453
|
-
--editorial-spotlight-hover-shadow:
|
|
453
|
+
--editorial-spotlight-hover-shadow: initial;
|
|
454
454
|
|
|
455
455
|
--editorial-journal-cover-height: 13.25rem;
|
|
456
456
|
|
|
@@ -490,7 +490,7 @@
|
|
|
490
490
|
--editorial-journal-arrow-size: 2rem;
|
|
491
491
|
--editorial-journal-arrow-icon-size: var(--icon-size-md);
|
|
492
492
|
--editorial-journal-focus-offset: -4px;
|
|
493
|
-
--editorial-journal-hover-shadow:
|
|
493
|
+
--editorial-journal-hover-shadow: initial;
|
|
494
494
|
|
|
495
495
|
--editorial-masthead-height: 5.5rem;
|
|
496
496
|
--editorial-masthead-gap: var(--space-8);
|
|
@@ -603,6 +603,9 @@
|
|
|
603
603
|
--editorial-catalog-detail-art-height: auto;
|
|
604
604
|
--editorial-catalog-detail-art-max-width: none;
|
|
605
605
|
--editorial-catalog-detail-art-padding: var(--space-10);
|
|
606
|
+
--editorial-catalog-detail-loading-background: initial;
|
|
607
|
+
--editorial-catalog-detail-loading-duration: var(--duration-loop);
|
|
608
|
+
--editorial-catalog-detail-loading-alpha: 0.5;
|
|
606
609
|
--editorial-catalog-detail-art-radius: calc(var(--radius) * 2);
|
|
607
610
|
--editorial-catalog-detail-media-width: 15.625rem;
|
|
608
611
|
--editorial-catalog-detail-media-height: 22.5rem;
|
package/docs/CONSUMER-RULES.md
CHANGED
|
@@ -4,6 +4,33 @@ Read this once; the audit enforces it. What the audit cannot see (how a screen i
|
|
|
4
4
|
should look like) is in the package's `DESIGN.md`. Everything else in `docs/` is for contributors.
|
|
5
5
|
|
|
6
6
|
1. Load styles with `import "@godxjp/ui/styles.css"` (precompiled, no Tailwind needed) or `@import "@godxjp/ui/styles"` (Tailwind v4). Neither ships font files: fonts are opt-in since v32 (`pnpm add @fontsource/noto-sans-jp @fontsource/m-plus-2`, then `@import "@godxjp/ui/styles/fonts.css"` after the styles import; the GoDX preset does this for you). Never cherry-pick `*-layout.css`.
|
|
7
|
+
|
|
8
|
+
**Supported opt-out for Tailwind v4 (#1475):** replace `@import "@godxjp/ui/styles"` with
|
|
9
|
+
`@import "@godxjp/ui/styles/application"` in apps that render no editorial, catalog or holding
|
|
10
|
+
components. It retains foundation, shell, controls, tables, forms, navigation, charts and vendor
|
|
11
|
+
styles. `styles` and `styles/core` retain every family for compatibility. If editorial components
|
|
12
|
+
are added later, return to `styles`, or import `styles/editorial` after `styles/application`.
|
|
13
|
+
`styles/editorial` is additive: it requires the application entry. All entries bring no bundled fonts.
|
|
14
|
+
|
|
15
|
+
For a smaller, content-aware build, run the package-owned pruner instead of guessing layers:
|
|
16
|
+
|
|
17
|
+
```sh
|
|
18
|
+
npx @godxjp/ui prune-css "src/**/*.tsx" --exclude-family editorial --out src/godx-ui.css
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Import the generated file instead of `@godxjp/ui/styles`; keep your Tailwind `@source` declarations.
|
|
22
|
+
The optional `--exclude-family editorial` fails if a detected component needs that family. Named
|
|
23
|
+
imports are required for a useful slice; namespace/dynamic imports conservatively retain all layers.
|
|
24
|
+
Both the family entries and the pruner use the generated `styles/layers.json` dependency map.
|
|
25
|
+
Re-run after component imports change and after upgrading the package. Never edit generated imports.
|
|
26
|
+
|
|
27
|
+
**Without Tailwind (#1455):** use the same command with `--precompiled`. The generated file
|
|
28
|
+
resolves package-owned plain CSS slices through public exports; bundle its CSS imports with your
|
|
29
|
+
existing CSS bundler (Vite, webpack or esbuild). It requires no Tailwind compiler. A browser alone
|
|
30
|
+
cannot resolve npm package specifiers. Fonts stay opt-in (`--fonts`). The packed-contract gate
|
|
31
|
+
installs the tarball outside the repository and builds both modes; reproduce its measured byte
|
|
32
|
+
counts with `pnpm build && node scripts/check-packed-css-pruning.mjs`.
|
|
33
|
+
|
|
7
34
|
2. **Mount `<AppProvider defaultLocale="…">` once, at the root.** Without it the kit's OWN strings (dialog close/cancel/delete, counters, picker labels) fall to the resting locale (`<html lang>` when it names a registered locale, else `en`) and pickers to UTC (gh#1005). A development build now warns once when a kit component renders outside it; `syncI18nLocale(locale, fallback)` is the escape for an app that truly cannot mount the provider. Every page is `<PageContainer title extra footer>` (a `subtitle` only when it adds a fact the title does not); its sections are spaced by the page. Group items inside a section with `<Flex direction="col" gap>` or `<ResponsiveGrid>`.
|
|
8
35
|
3. No Tailwind layout on your own elements: no `flex`, `grid`, `gap-*`, `p-*`, `m-*`, `space-*`. Rows are `<Flex>` (default row), stacks are `<Flex direction="col">`, grids are `<ResponsiveGrid>`. A list's filters are ONE `<FilterBar>` that wraps at every width — never a sideways-scrolling strip of filters or filter chips; past 2–4 filters the rest go behind one "More filters" `Sheet` (cardinal rule #51, pattern `list-filters`, audit rules `filter-bar-no-overflow`, `filter-strip-no-scroll` and `hand-rolled-filter-bar`). Filters are packed at the start: never a hand-built `<Flex justify="between">` of FormFields above a table. Many conditions or an explicit 検索 button → `SearchForm` (pattern `search-form`); field × operator rows saved as views → pattern `condition-builder`.
|
|
9
36
|
4. No hand-rolled surfaces: no `rounded-* border bg-*` divs. A box is `Card`, a pill is `Badge`, a person is `Avatar`, a row is `ListRow`, a label/value pair is `Descriptions`, an empty area is `EmptyState`, a read-only sample of a colour the USER chose is `Swatch`. A LIST of those rows is `<Flex as="ul" marker="none" direction="col" gap="none">` with `<ListRow as="li">` children — `marker="none"` keeps the `<ul>`, the `<li>` semantics and the gap token while dropping the bullet and the indent. Never a raw `<ul>`/`<ol>` (it carries no gap token), never `<div role="list">` + `<div role="listitem">`, and never a wrapper around each row: the divider is `:not(:last-child)` among siblings, so a row alone in its own wrapper is always the last one and EVERY divider disappears silently. A bulleted prose list is the same `<Flex as="ul">` without `marker`.
|
|
@@ -54,3 +81,11 @@ information belongs on the screen:
|
|
|
54
81
|
If the control is disabled _pending something the user can fix_, prefer leaving it enabled and
|
|
55
82
|
explaining on submit: an inert control with a paragraph beside it is often a validation message
|
|
56
83
|
wearing a disguise.
|
|
84
|
+
|
|
85
|
+
## Floating content and toast imports
|
|
86
|
+
|
|
87
|
+
Use `DropdownMenuContent` only for menu collection nodes (`DropdownMenuItem`, checkbox/radio items, groups, labels and separators). Arbitrary notification headers, lists and links use `Popover` + `ListRow`. Development diagnostics and `dropdown-menu-non-menu-children` identify unsupported DOM children. Opaque components returning menu items remain supported.
|
|
88
|
+
|
|
89
|
+
`PopoverContent` scrolls automatically when the available viewport height caps it; focus rings stay inside the scroll boundary, including `flush` content.
|
|
90
|
+
|
|
91
|
+
Always use `import { toast } from "@godxjp/ui"` (or `@godxjp/ui/feedback`) with the kit's `Toaster`. Do not import toast directly from `sonner`: an app-installed version can create a separate toast store and calls never reach the kit's Toaster. The `no-direct-sonner-import` audit rule flags runtime imports. Sonner remains a dependency; no peer dependency migration is required.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@godxjp/ui",
|
|
3
|
-
"version": "33.
|
|
4
|
-
"godxUiMcp": "33.
|
|
3
|
+
"version": "33.25.0",
|
|
4
|
+
"godxUiMcp": "33.25.0",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -81,6 +81,8 @@
|
|
|
81
81
|
"import": "./dist/lab/index.js"
|
|
82
82
|
},
|
|
83
83
|
"./styles": "./dist/styles/index.css",
|
|
84
|
+
"./styles/application": "./dist/styles/application.css",
|
|
85
|
+
"./styles/editorial": "./dist/styles/editorial.css",
|
|
84
86
|
"./styles/core": "./dist/styles/core.css",
|
|
85
87
|
"./styles/core-with-fallbacks": "./dist/styles/core-with-fallbacks.css",
|
|
86
88
|
"./styles/core-with-jis-level1": "./dist/styles/core-with-jis-level1.css",
|
package/scripts/prune-css.mjs
CHANGED
|
@@ -40,18 +40,25 @@ const args = process.argv.slice(2);
|
|
|
40
40
|
if (args.includes("--help") || args.includes("-h") || args.length === 0) {
|
|
41
41
|
console.log(`prune-css — emit a stylesheet with only the @godxjp/ui CSS layers your app uses
|
|
42
42
|
|
|
43
|
-
usage: node node_modules/@godxjp/ui/scripts/prune-css.mjs <src dir/glob …> [--out <file>] [--fonts]
|
|
43
|
+
usage: node node_modules/@godxjp/ui/scripts/prune-css.mjs <src dir/glob …> [--out <file>] [--fonts] [--precompiled]
|
|
44
44
|
|
|
45
45
|
<src dir/glob …> where your app's source lives (directories are walked; globs expand)
|
|
46
46
|
--out <file> where to write the css (default: godx-ui.css in the current directory)
|
|
47
|
+
--exclude-family <name> fail if detected components require the omitted family (e.g. editorial)
|
|
47
48
|
--fonts include the bundled M PLUS 2 / Noto Sans JP @font-face declarations
|
|
48
49
|
(default mirrors @godxjp/ui/styles/core: none — bring your own fonts)
|
|
50
|
+
--precompiled import the precompiled slices (plain CSS, dist/styles/precompiled/) instead
|
|
51
|
+
of the Tailwind sources: for apps that use @godxjp/ui/styles.css and have
|
|
52
|
+
no Tailwind compiler (gh#1455)
|
|
49
53
|
|
|
50
|
-
Then import the emitted file INSTEAD of "@godxjp/ui/styles"
|
|
54
|
+
Then import the emitted file INSTEAD of "@godxjp/ui/styles" (or "@godxjp/ui/styles.css" with
|
|
55
|
+
--precompiled) and re-run this command whenever
|
|
51
56
|
the set of components you use changes, and after every @godxjp/ui upgrade.`);
|
|
52
57
|
process.exit(0);
|
|
53
58
|
}
|
|
54
59
|
|
|
60
|
+
const excludeFlag = args.indexOf("--exclude-family");
|
|
61
|
+
const excludedFamily = excludeFlag === -1 ? undefined : args[excludeFlag + 1];
|
|
55
62
|
const outFlag = args.indexOf("--out");
|
|
56
63
|
const OUT = outFlag !== -1 ? args[outFlag + 1] : "godx-ui.css";
|
|
57
64
|
if (outFlag !== -1 && (!OUT || OUT.startsWith("--"))) {
|
|
@@ -59,8 +66,12 @@ if (outFlag !== -1 && (!OUT || OUT.startsWith("--"))) {
|
|
|
59
66
|
process.exit(2);
|
|
60
67
|
}
|
|
61
68
|
const FONTS = args.includes("--fonts");
|
|
69
|
+
const PRECOMPILED = args.includes("--precompiled");
|
|
62
70
|
const positionals = args.filter(
|
|
63
|
-
(a, i) =>
|
|
71
|
+
(a, i) =>
|
|
72
|
+
!a.startsWith("--") &&
|
|
73
|
+
(outFlag === -1 || i !== outFlag + 1) &&
|
|
74
|
+
(excludeFlag === -1 || i !== excludeFlag + 1),
|
|
64
75
|
);
|
|
65
76
|
|
|
66
77
|
// ── the package's own graph, version-locked ──────────────────────────────────
|
|
@@ -85,6 +96,13 @@ if (manifest.version !== pkg.version) {
|
|
|
85
96
|
process.exit(2);
|
|
86
97
|
}
|
|
87
98
|
|
|
99
|
+
if (excludeFlag !== -1 && !Object.hasOwn(manifest.families ?? {}, excludedFamily ?? "")) {
|
|
100
|
+
console.error(
|
|
101
|
+
`prune-css: unknown --exclude-family ${excludedFamily ?? "(missing)"}; choose ${Object.keys(manifest.families ?? {}).join(", ")}`,
|
|
102
|
+
);
|
|
103
|
+
process.exit(2);
|
|
104
|
+
}
|
|
105
|
+
|
|
88
106
|
// ── scan consumer sources ────────────────────────────────────────────────────
|
|
89
107
|
|
|
90
108
|
const SCANNABLE = /\.(tsx|jsx|ts|mjs|js|cjs|mts)$/;
|
|
@@ -184,9 +202,35 @@ for (const name of used) {
|
|
|
184
202
|
for (const v of entry.vendor ?? []) vendors.add(v);
|
|
185
203
|
}
|
|
186
204
|
|
|
205
|
+
if (excludedFamily && manifest.families[excludedFamily].some((file) => layers.has(file))) {
|
|
206
|
+
console.error(
|
|
207
|
+
`prune-css: cannot exclude ${excludedFamily}: detected components require it. Remove their imports or keep the family.`,
|
|
208
|
+
);
|
|
209
|
+
process.exit(2);
|
|
210
|
+
}
|
|
211
|
+
|
|
187
212
|
const keptLayers = manifest.order.filter((f) => layers.has(f));
|
|
188
213
|
const keptVendors = manifest.vendor.filter((f) => vendors.has(f));
|
|
189
|
-
|
|
214
|
+
// --precompiled (gh#1455): the same slice, from the plain-CSS cut of styles.css that
|
|
215
|
+
// build-precompiled-css.mjs writes per manifest file. The fonts sheet has no Tailwind in it, so it
|
|
216
|
+
// is imported from its usual place either way.
|
|
217
|
+
const asImport = (f) =>
|
|
218
|
+
PRECOMPILED && f !== manifest.fonts
|
|
219
|
+
? `@import "@godxjp/ui/styles/precompiled/${f.replace(/\.css$/, "")}";`
|
|
220
|
+
: `@import "@godxjp/ui/styles/${f.replace(/\.css$/, "")}";`;
|
|
221
|
+
if (PRECOMPILED) {
|
|
222
|
+
const missing = [...keptVendors, manifest.base, ...keptLayers].filter(
|
|
223
|
+
(f) => !existsSync(join(PKG_ROOT, "dist/styles/precompiled", f)),
|
|
224
|
+
);
|
|
225
|
+
if (missing.length) {
|
|
226
|
+
console.error(
|
|
227
|
+
`prune-css: --precompiled, but the installed @godxjp/ui ships no precompiled slice for ` +
|
|
228
|
+
`${missing.join(", ")} (dist/styles/precompiled/). Upgrade the package; inside the repo ` +
|
|
229
|
+
"itself, run `pnpm build` first.",
|
|
230
|
+
);
|
|
231
|
+
process.exit(2);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
190
234
|
|
|
191
235
|
const lines = [
|
|
192
236
|
"/*",
|
|
@@ -194,17 +238,21 @@ const lines = [
|
|
|
194
238
|
` *`,
|
|
195
239
|
` * @godxjp/ui version: ${pkg.version}`,
|
|
196
240
|
` * components detected: ${[...used].sort().join(", ")}`,
|
|
197
|
-
` * layers: ${keptLayers.length} of ${manifest.order.length} (+base${FONTS ? "+fonts" : ", no bundled fonts — like styles/core"})`,
|
|
241
|
+
` * layers: ${keptLayers.length} of ${manifest.order.length} (+base${FONTS ? "+fonts" : ", no bundled fonts — like styles/core"})${PRECOMPILED ? ", precompiled (no Tailwind needed)" : ""}`,
|
|
198
242
|
` *`,
|
|
199
243
|
` * Re-run when the components your app uses change, and after every @godxjp/ui upgrade:`,
|
|
200
|
-
` * node node_modules/@godxjp/ui/scripts/prune-css.mjs <src …> --out <this file>${FONTS ? " --fonts" : ""}`,
|
|
244
|
+
` * node node_modules/@godxjp/ui/scripts/prune-css.mjs <src …> --out <this file>${FONTS ? " --fonts" : ""}${PRECOMPILED ? " --precompiled" : ""}`,
|
|
201
245
|
` *`,
|
|
202
246
|
` * Hand-editing this file is the cherry-picking the README forbids: layers share rules and`,
|
|
203
247
|
` * a missing one fails silently. Change your imports, then re-run the tool.`,
|
|
204
248
|
" */",
|
|
205
249
|
// Layer order must be declared before the first @import — same statement, same reasoning,
|
|
206
|
-
// as styles/index.css (vendor between base and components; see the comment there).
|
|
207
|
-
|
|
250
|
+
// as styles/index.css (vendor between base and components; see the comment there). Precompiled
|
|
251
|
+
// CSS also carries Tailwind's `properties` layer (the @property fallbacks), which the compiler
|
|
252
|
+
// puts FIRST in styles.css; named here, it keeps that place instead of landing after utilities.
|
|
253
|
+
PRECOMPILED
|
|
254
|
+
? "@layer properties, theme, base, vendor, components, utilities;"
|
|
255
|
+
: "@layer theme, base, vendor, components, utilities;",
|
|
208
256
|
...keptVendors.map(asImport),
|
|
209
257
|
asImport(manifest.base),
|
|
210
258
|
...(FONTS ? [asImport(manifest.fonts)] : []),
|
package/scripts/ui-audit.mjs
CHANGED
|
@@ -366,6 +366,27 @@ const LIST_TAGS = new Set(["DataTable", "Table", "List", "ListRow"]);
|
|
|
366
366
|
* CSS Logical Properties L1 (W3C) · HTML Living Standard (WHATWG).
|
|
367
367
|
*/
|
|
368
368
|
const RULES = [
|
|
369
|
+
{
|
|
370
|
+
id: "no-direct-sonner-import",
|
|
371
|
+
replacement: "import { toast } from '@godxjp/ui'",
|
|
372
|
+
scope: "consumer",
|
|
373
|
+
severity: "error",
|
|
374
|
+
spansElement: true,
|
|
375
|
+
test: /\bimport\s+(?!type\b)(?:[^;"']*?\s+from\s*)?["']sonner["']/g,
|
|
376
|
+
message:
|
|
377
|
+
"import toast from @godxjp/ui — use `import { toast } from \"@godxjp/ui\"`; a consumer's sonner may own a different toast store from the kit's Toaster.",
|
|
378
|
+
},
|
|
379
|
+
{
|
|
380
|
+
id: "dropdown-menu-non-menu-children",
|
|
381
|
+
replacement: "Popover + ListRow",
|
|
382
|
+
scope: "consumer",
|
|
383
|
+
severity: "error",
|
|
384
|
+
spansElement: true,
|
|
385
|
+
matches: dropdownNonMenuMatches,
|
|
386
|
+
message:
|
|
387
|
+
"DropdownMenuContent accepts menu collection children only. Use DropdownMenuItem for actions; use Popover + ListRow for arbitrary headers, lists and links.",
|
|
388
|
+
},
|
|
389
|
+
|
|
369
390
|
{
|
|
370
391
|
id: "no-utility-spacing",
|
|
371
392
|
replacement: "Flex gap / ResponsiveGrid / PageContainer",
|
|
@@ -2936,3 +2957,18 @@ if (filesScanned === 0 && !changedNoFiles) {
|
|
|
2936
2957
|
|
|
2937
2958
|
// See the note above --rules: exitCode, so a large JSON report drains fully.
|
|
2938
2959
|
if (filesScanned > 0 || changedNoFiles) process.exitCode = errors.length > 0 ? 1 : 0;
|
|
2960
|
+
|
|
2961
|
+
/** Known DOM children are invalid collection nodes; opaque wrappers are deliberately allowed. */
|
|
2962
|
+
function* dropdownNonMenuMatches(source) {
|
|
2963
|
+
const containers = new Set([
|
|
2964
|
+
"DropdownMenuContent",
|
|
2965
|
+
"DropdownMenuSubContent",
|
|
2966
|
+
"DropdownMenuGroup",
|
|
2967
|
+
"DropdownMenuRadioGroup",
|
|
2968
|
+
]);
|
|
2969
|
+
for (const { tag, index, openTag, stack } of jsxElements(source)) {
|
|
2970
|
+
if (!/^[a-z]/.test(tag)) continue;
|
|
2971
|
+
const parent = [...stack].reverse().find((frame) => !frame.attr && frame.tag !== "");
|
|
2972
|
+
if (parent && containers.has(parent.tag)) yield { 0: openTag, index };
|
|
2973
|
+
}
|
|
2974
|
+
}
|