@godxjp/ui 28.2.0 → 28.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.
@@ -49,6 +49,21 @@ export type CommandPaletteProps = {
49
49
  shouldFilter?: boolean;
50
50
  loading?: boolean;
51
51
  error?: React.ReactNode;
52
+ /**
53
+ * The control that opens the palette.
54
+ *
55
+ * `undefined` (omitted) — the default outline Button with the ⌘K hint.
56
+ * `null` — **NO trigger at all**, for a palette driven purely by `shortcut`.
57
+ *
58
+ * The two are deliberately NOT the same, and that is the whole point of gh#778: the previous
59
+ * `trigger ?? <default/>` collapsed them, so `null` — the spelling every consumer reaches for —
60
+ * silently rendered the very Button it was asked to remove. The only working spelling was
61
+ * `trigger={<></>}`, which is a hack that renders an empty fragment into the trigger slot.
62
+ *
63
+ * A keyboard-only palette is a NORMAL shape: `shortcut` already binds ⌘K/Ctrl+K and handles
64
+ * `event.isComposing` (i.e. every keystroke of a Japanese IME) and focus restore, so it is a
65
+ * better handler than a consumer's own. A topbar with no width to spare should be able to say so.
66
+ */
52
67
  trigger?: React.ReactNode;
53
68
  shortcut?: boolean;
54
69
  };
@@ -73,13 +73,13 @@ function CommandPalette({
73
73
  return () => document.removeEventListener("keydown", handleKeyDown);
74
74
  }, [open, setOpen, shortcut]);
75
75
  const hasItems = React.useMemo(() => groups.some((group) => group.items.length > 0), [groups]);
76
- const triggerNode = trigger ?? /* @__PURE__ */ jsxs(Button, { variant: "outline", size: "sm", className: "ui-command-palette-trigger", children: [
76
+ const triggerNode = trigger === void 0 ? /* @__PURE__ */ jsxs(Button, { variant: "outline", size: "sm", className: "ui-command-palette-trigger", children: [
77
77
  /* @__PURE__ */ jsx(Search, { "aria-hidden": "true" }),
78
78
  /* @__PURE__ */ jsx("span", { children: labels.open }),
79
79
  /* @__PURE__ */ jsx("span", { className: "kbd", "aria-hidden": "true", children: "\u2318K" })
80
- ] });
80
+ ] }) : trigger;
81
81
  return /* @__PURE__ */ jsxs(Dialog, { open, onOpenChange: setOpen, children: [
82
- /* @__PURE__ */ jsx(Dialog.Trigger, { asChild: true, children: triggerNode }),
82
+ triggerNode === null ? null : /* @__PURE__ */ jsx(Dialog.Trigger, { asChild: true, children: triggerNode }),
83
83
  /* @__PURE__ */ jsxs(
84
84
  DialogContent,
85
85
  {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$comment": "AUTO-GENERATED by scripts/gen-measurement-contract.mjs — do not edit. Read this instead of guessing: docs/MEASUREMENT-CONTRACT.md.",
3
- "version": "28.2.0",
3
+ "version": "28.3.0",
4
4
  "targetSize": {
5
5
  "standard": "WCAG 2.2 SC 2.5.8 Target Size (Minimum), level AA — 24×24 CSS px",
6
6
  "min": 24,
@@ -2,7 +2,15 @@
2
2
  import type * as React from "react";
3
3
  /** @see CodeBlock — a block of preformatted text (request bodies, logs, snippets). */
4
4
  export type CodeBlockProp = {
5
- /** The text. Pass a string; a highlighter's spans also work. */
5
+ /**
6
+ * The text. Pass a string, or a highlighter's spans.
7
+ *
8
+ * Tag each span `data-code-token="keyword" | "string" | "comment" | …` — the twelve names Shiki's
9
+ * `createCssVariablesTheme` emits — and the package colours it from the `--code-block-token-*`
10
+ * knobs. Do NOT put `style={{ color }}` or a palette `className` on the spans: both are visual
11
+ * overrides, and this used to be the only spelling available, which made the documented path
12
+ * unbuildable for a rule-following consumer (gh#784).
13
+ */
6
14
  children?: ChildrenProp;
7
15
  /** Soft-wrap long lines (default true). `false` scrolls horizontally instead. */
8
16
  wrap?: boolean;
@@ -12,7 +20,7 @@ export type CodeBlockProp = {
12
20
  };
13
21
  /** Type size. Default `sm`. */
14
22
  size?: Extract<SizeProp, "xs" | "sm">;
15
- /** Cosmetic: lands on `data-language`; no highlighter is bundled. */
23
+ /** Lands on `data-language`; no highlighter is bundled — see `children` for colouring its output. */
16
24
  language?: string;
17
25
  className?: ClassNameProp;
18
26
  };
@@ -973,7 +973,7 @@
973
973
  border-radius: var(--code-block-radius);
974
974
  background: hsl(var(--muted));
975
975
  padding: var(--code-block-space-inset);
976
- color: hsl(var(--foreground));
976
+ color: var(--code-block-foreground, hsl(var(--foreground)));
977
977
  font-family: var(--font-mono);
978
978
  font-size: var(--code-block-font-size);
979
979
  line-height: var(--code-block-line-height);
@@ -1009,6 +1009,65 @@
1009
1009
  max-block-size: var(--code-block-max-height-lg);
1010
1010
  }
1011
1011
 
1012
+ .ui-code-block [data-code-token="comment"],
1013
+ .ui-prose pre [data-code-token="comment"] {
1014
+ color: var(--code-block-token-comment-color, hsl(var(--muted-foreground)));
1015
+ }
1016
+
1017
+ .ui-code-block [data-code-token="keyword"],
1018
+ .ui-prose pre [data-code-token="keyword"] {
1019
+ color: var(--code-block-token-keyword-color, hsl(var(--primary)));
1020
+ }
1021
+
1022
+ .ui-code-block [data-code-token="string"],
1023
+ .ui-prose pre [data-code-token="string"] {
1024
+ color: var(--code-block-token-string-color, hsl(var(--text-success)));
1025
+ }
1026
+
1027
+ .ui-code-block [data-code-token="string-expression"],
1028
+ .ui-prose pre [data-code-token="string-expression"] {
1029
+ color: var(--code-block-token-string-expression-color, hsl(var(--text-success)));
1030
+ }
1031
+
1032
+ .ui-code-block [data-code-token="function"],
1033
+ .ui-prose pre [data-code-token="function"] {
1034
+ color: var(--code-block-token-function-color, hsl(var(--text-info)));
1035
+ }
1036
+
1037
+ .ui-code-block [data-code-token="constant"],
1038
+ .ui-prose pre [data-code-token="constant"] {
1039
+ color: var(--code-block-token-constant-color, hsl(var(--text-warning)));
1040
+ }
1041
+
1042
+ .ui-code-block [data-code-token="parameter"],
1043
+ .ui-prose pre [data-code-token="parameter"] {
1044
+ color: var(--code-block-token-parameter-color, hsl(var(--foreground)));
1045
+ }
1046
+
1047
+ .ui-code-block [data-code-token="punctuation"],
1048
+ .ui-prose pre [data-code-token="punctuation"] {
1049
+ color: var(--code-block-token-punctuation-color, hsl(var(--muted-foreground)));
1050
+ }
1051
+
1052
+ .ui-code-block [data-code-token="link"],
1053
+ .ui-prose pre [data-code-token="link"] {
1054
+ color: var(--code-block-token-link-color, hsl(var(--text-link)));
1055
+ text-decoration-line: underline;
1056
+
1057
+ text-underline-offset: var(--text-link-underline-offset);
1058
+ text-decoration-skip-ink: auto;
1059
+ }
1060
+
1061
+ .ui-code-block [data-code-token="inserted"],
1062
+ .ui-prose pre [data-code-token="inserted"] {
1063
+ color: var(--code-block-token-inserted-color, hsl(var(--text-success)));
1064
+ }
1065
+
1066
+ .ui-code-block [data-code-token="deleted"],
1067
+ .ui-prose pre [data-code-token="deleted"] {
1068
+ color: var(--code-block-token-deleted-color, hsl(var(--text-error)));
1069
+ }
1070
+
1012
1071
  .ui-prose {
1013
1072
  font-size: var(--prose-font-size);
1014
1073
  line-height: var(--prose-line-height);
@@ -220,27 +220,27 @@
220
220
  }
221
221
 
222
222
  [data-slot="tabs"][data-variant="card"][data-placement="start"] [data-slot="tabs-list"],
223
- [data-slot="tabs"][data-variant="editable-card"][data-placement="start"] [data-slot="tabs-list"] {
223
+ [data-slot="tabs"][data-variant="editable-card"][data-placement="start"]
224
+ [data-slot="tabs-list"] {
224
225
  box-shadow: inset calc(-1 * var(--tabs-card-rail-border-width)) 0 0 hsl(var(--border));
225
226
  }
226
227
 
227
228
  [data-slot="tabs"][data-variant="card"][data-placement="end"] [data-slot="tabs-list"],
228
- [data-slot="tabs"][data-variant="editable-card"][data-placement="end"] [data-slot="tabs-list"] {
229
+ [data-slot="tabs"][data-variant="editable-card"][data-placement="end"]
230
+ [data-slot="tabs-list"] {
229
231
  box-shadow: inset var(--tabs-card-rail-border-width) 0 0 hsl(var(--border));
230
232
  }
231
233
 
232
- [dir="rtl"]
233
- [data-slot="tabs"][data-variant="card"][data-placement="start"]
234
+ [dir="rtl"] [data-slot="tabs"][data-variant="card"][data-placement="start"]
234
235
  [data-slot="tabs-list"],
235
- [dir="rtl"]
236
- [data-slot="tabs"][data-variant="editable-card"][data-placement="start"]
236
+ [dir="rtl"] [data-slot="tabs"][data-variant="editable-card"][data-placement="start"]
237
237
  [data-slot="tabs-list"] {
238
238
  box-shadow: inset var(--tabs-card-rail-border-width) 0 0 hsl(var(--border));
239
239
  }
240
240
 
241
- [dir="rtl"] [data-slot="tabs"][data-variant="card"][data-placement="end"] [data-slot="tabs-list"],
242
- [dir="rtl"]
243
- [data-slot="tabs"][data-variant="editable-card"][data-placement="end"]
241
+ [dir="rtl"] [data-slot="tabs"][data-variant="card"][data-placement="end"]
242
+ [data-slot="tabs-list"],
243
+ [dir="rtl"] [data-slot="tabs"][data-variant="editable-card"][data-placement="end"]
244
244
  [data-slot="tabs-list"] {
245
245
  box-shadow: inset calc(-1 * var(--tabs-card-rail-border-width)) 0 0 hsl(var(--border));
246
246
  }
@@ -277,7 +277,7 @@
277
277
  margin-inline-start: calc(var(--tabs-panel-space-inset) + var(--tabs-panel-border-width));
278
278
  }
279
279
 
280
- [data-slot="tabs"][data-bodied="true"] > [data-slot="tabs-panel"],
280
+ [data-slot="tabs"][data-bodied="true"] > [data-slot="tabs-panel"],
281
281
  [data-slot="tabs"][data-bodied="true"] > [data-slot="tabs-content"] {
282
282
  border: var(--tabs-panel-border-width) solid hsl(var(--border));
283
283
  border-radius: var(--tabs-panel-radius);
@@ -2003,6 +2003,8 @@
2003
2003
  }
2004
2004
  .ui-topbar-start {
2005
2005
  flex: 0 1 auto;
2006
+
2007
+ min-inline-size: var(--topbar-item-min-width);
2006
2008
  }
2007
2009
 
2008
2010
  .ui-topbar-start > :last-child:not(:is(button, a, [role="button"], .ui-button)) {
@@ -2041,10 +2043,6 @@
2041
2043
  min-inline-size: auto;
2042
2044
  }
2043
2045
 
2044
- .ui-topbar[data-overflow="scroll"] > .ui-topbar-start {
2045
- min-inline-size: var(--topbar-item-min-width);
2046
- }
2047
-
2048
2046
  .ui-topbar-item {
2049
2047
  display: inline-flex;
2050
2048
  min-width: var(--topbar-item-min-width);
@@ -18,6 +18,19 @@
18
18
  --code-block-max-height-md: 20rem;
19
19
  --code-block-max-height-lg: 32rem;
20
20
 
21
+ --code-block-foreground: initial;
22
+ --code-block-token-comment-color: initial;
23
+ --code-block-token-keyword-color: initial;
24
+ --code-block-token-string-color: initial;
25
+ --code-block-token-string-expression-color: initial;
26
+ --code-block-token-function-color: initial;
27
+ --code-block-token-constant-color: initial;
28
+ --code-block-token-parameter-color: initial;
29
+ --code-block-token-punctuation-color: initial;
30
+ --code-block-token-link-color: initial;
31
+ --code-block-token-inserted-color: initial;
32
+ --code-block-token-deleted-color: initial;
33
+
21
34
  --prose-font-size: var(--font-size-base);
22
35
  --prose-font-size-sm: var(--font-size-xs);
23
36
  --prose-line-height: var(--line-height-body);
@@ -84,6 +84,74 @@ export default function Demo() {
84
84
  </Flex>
85
85
  </CardContent>
86
86
  </Card>
87
+ <Card>
88
+ <CardHeader>
89
+ <CardTitle level={2}>Syntax colour · the package owns the palette (gh#784)</CardTitle>
90
+ <CardDescription>
91
+ CodeBlock bundles no highlighter. Bring your own, then tag each span with
92
+ data-code-token and the package colours it. The twelve names are Shiki
93
+ createCssVariablesTheme&apos;s verbatim, so mapping is a rename rather than a
94
+ translation. Note what the consumer never writes: no style attribute, no palette
95
+ class. Every knob is a role-mirror, so this follows the theme into dark with no second
96
+ palette.
97
+ </CardDescription>
98
+ </CardHeader>
99
+ <CardContent>
100
+ <CodeBlock language="ts" aria-label="Highlighted TypeScript">
101
+ <span data-code-token="comment">{"// resolve the active tenant\n"}</span>
102
+ <span data-code-token="keyword">export</span>{" "}
103
+ <span data-code-token="keyword">async</span>{" "}
104
+ <span data-code-token="keyword">function</span>{" "}
105
+ <span data-code-token="function">loadTenant</span>
106
+ <span data-code-token="punctuation">(</span>
107
+ <span data-code-token="parameter">slug</span>
108
+ <span data-code-token="punctuation">:</span>{" "}
109
+ <span data-code-token="constant">string</span>
110
+ <span data-code-token="punctuation">)</span>{" "}
111
+ <span data-code-token="punctuation">{"{"}</span>
112
+ {"\n "}
113
+ <span data-code-token="keyword">const</span> res{" "}
114
+ <span data-code-token="punctuation">=</span>{" "}
115
+ <span data-code-token="keyword">await</span>{" "}
116
+ <span data-code-token="function">fetch</span>
117
+ <span data-code-token="punctuation">(</span>
118
+ <span data-code-token="string">{"`/api/tenants/"}</span>
119
+ <span data-code-token="string-expression">{"${slug}"}</span>
120
+ <span data-code-token="string">{"`"}</span>
121
+ <span data-code-token="punctuation">)</span>
122
+ <span data-code-token="punctuation">;</span>
123
+ {"\n "}
124
+ <span data-code-token="keyword">return</span> res
125
+ <span data-code-token="punctuation">.</span>
126
+ <span data-code-token="function">json</span>
127
+ <span data-code-token="punctuation">()</span>
128
+ <span data-code-token="punctuation">;</span>
129
+ {"\n"}
130
+ <span data-code-token="punctuation">{"}"}</span>
131
+ </CodeBlock>
132
+ </CardContent>
133
+ </Card>
134
+
135
+ <Card>
136
+ <CardHeader>
137
+ <CardTitle level={2}>Diff tokens · inserted and deleted</CardTitle>
138
+ <CardDescription>
139
+ The same vocabulary carries a diff. inserted and deleted default to the success and
140
+ destructive roles, so they agree with every other affirmative and destructive mark in
141
+ the system rather than inventing a second green and red.
142
+ </CardDescription>
143
+ </CardHeader>
144
+ <CardContent>
145
+ <CodeBlock language="diff" aria-label="Patch">
146
+ <span data-code-token="comment">{"--- a/tokens.css\n+++ b/tokens.css\n"}</span>
147
+ <span data-code-token="deleted">{"- --code-block-foreground: #111;\n"}</span>
148
+ <span data-code-token="inserted">{"+ --code-block-foreground: initial;\n"}</span>
149
+ <span data-code-token="punctuation">
150
+ {" /* role-mirror: the default moved to the call site */"}
151
+ </span>
152
+ </CodeBlock>
153
+ </CardContent>
154
+ </Card>
87
155
  </Flex>
88
156
  </PageContainer>
89
157
  );
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@godxjp/ui",
3
- "version": "28.2.0",
4
- "godxUiMcp": "28.2.0",
3
+ "version": "28.3.0",
4
+ "godxUiMcp": "28.3.0",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
7
7
  "type": "git",
@@ -410,7 +410,8 @@
410
410
  "check:mcp-token-sync": "node scripts/gen-component-tokens.mjs --check",
411
411
  "check:email-token-sync": "node scripts/gen-email-tokens.mjs --check",
412
412
  "check:focus-ring-paint": "node scripts/check-focus-ring-paint.mjs",
413
- "typecheck:mcp": "node node_modules/typescript-7/bin/tsc --noEmit -p mcp/tsconfig.json"
413
+ "typecheck:mcp": "node node_modules/typescript-7/bin/tsc --noEmit -p mcp/tsconfig.json",
414
+ "check:pr-closes-keyword": "node scripts/check-pr-closes-keyword.mjs"
414
415
  },
415
416
  "peerDependencies": {
416
417
  "@hookform/resolvers": "^5.2.0",