@godxjp/ui 31.7.0 → 31.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/agent/START-HERE.md +4 -4
  2. package/agent/components/ColorPicker.json +16 -8
  3. package/agent/components/Select.json +22 -0
  4. package/agent/components.json +38 -8
  5. package/agent/index.json +4 -4
  6. package/agent/llms.txt +5 -5
  7. package/agent/tokens.json +24 -0
  8. package/dist/components/data-entry/chat-composer.js +11 -4
  9. package/dist/components/data-entry/chat-suggestion.js +2 -0
  10. package/dist/components/data-entry/color-picker.d.ts +2 -2
  11. package/dist/components/data-entry/color-picker.js +150 -37
  12. package/dist/components/data-entry/command-palette.js +2 -1
  13. package/dist/components/data-entry/date-picker.js +2 -0
  14. package/dist/components/data-entry/index.d.ts +1 -1
  15. package/dist/components/data-entry/number-input.js +2 -1
  16. package/dist/components/data-entry/search-select.js +55 -17
  17. package/dist/components/data-entry/select.js +1 -1
  18. package/dist/components/data-entry/time-picker.js +3 -0
  19. package/dist/components/feedback/non-modal-layer.js +2 -1
  20. package/dist/components/general/typography.js +5 -1
  21. package/dist/components/navigation/pagination.js +2 -1
  22. package/dist/components/ui/tag-input.js +2 -1
  23. package/dist/contracts/measurement.json +1 -1
  24. package/dist/i18n/messages/en.json +4 -2
  25. package/dist/i18n/messages/ja.json +4 -2
  26. package/dist/i18n/messages/vi.json +4 -2
  27. package/dist/lib/ime.d.ts +12 -0
  28. package/dist/lib/ime.js +7 -0
  29. package/dist/props/components/data-entry.prop.d.ts +66 -1
  30. package/dist/props/components/index.d.ts +1 -1
  31. package/dist/props/registry.d.ts +15 -0
  32. package/dist/props/registry.js +17 -0
  33. package/dist/styles/control.css +79 -0
  34. package/dist/styles/layers.json +1 -1
  35. package/dist/tokens/components/control.css +8 -0
  36. package/docs/data-entry/color-picker.tsx +72 -0
  37. package/docs/data-entry/select.tsx +38 -0
  38. package/docs/i18n/messages/en.json +18 -0
  39. package/docs/i18n/messages/ja.json +18 -0
  40. package/docs/i18n/messages/vi.json +18 -0
  41. package/package.json +2 -2
@@ -738,6 +738,85 @@
738
738
  text-transform: uppercase;
739
739
  }
740
740
 
741
+ .ui-color-picker[data-panel] {
742
+ flex-direction: column;
743
+ align-items: stretch;
744
+ }
745
+
746
+ .ui-color-picker-picker {
747
+ display: flex;
748
+ align-items: center;
749
+ gap: var(--control-gap);
750
+ }
751
+
752
+ .ui-color-picker-presets {
753
+ display: flex;
754
+ flex-direction: column;
755
+ gap: var(--color-picker-presets-gap);
756
+ }
757
+
758
+ .ui-color-picker-presets-trigger {
759
+ display: inline-flex;
760
+ align-items: center;
761
+ gap: var(--space-1);
762
+ min-block-size: var(--touch-target-min);
763
+ color: hsl(var(--muted-foreground));
764
+ font-size: var(--color-picker-presets-font-size);
765
+ text-align: start;
766
+ }
767
+
768
+ .ui-color-picker-presets-chevron {
769
+ width: var(--control-icon-size);
770
+ height: var(--control-icon-size);
771
+ flex-shrink: 0;
772
+ transition: rotate 150ms;
773
+ }
774
+
775
+ .ui-color-picker-presets-trigger[data-state="closed"] .ui-color-picker-presets-chevron {
776
+ rotate: -90deg;
777
+ }
778
+
779
+ .ui-color-picker-presets-trigger[data-state="closed"]:dir(rtl) .ui-color-picker-presets-chevron {
780
+ rotate: 90deg;
781
+ }
782
+
783
+ .ui-color-picker-presets-items {
784
+ display: flex;
785
+ flex-wrap: wrap;
786
+ gap: var(--color-picker-preset-gap);
787
+ padding-block: var(--space-1);
788
+ }
789
+
790
+ .ui-color-picker-presets-color {
791
+ display: inline-block;
792
+ flex-shrink: 0;
793
+ inline-size: var(--color-picker-preset-size);
794
+ block-size: var(--color-picker-preset-size);
795
+ border: var(--stroke-hairline) solid hsl(var(--input) / var(--input-alpha, 100%));
796
+ border-radius: var(--control-radius);
797
+ background-color: var(--color-picker-preset-color, transparent);
798
+ cursor: pointer;
799
+ forced-color-adjust: none;
800
+ }
801
+
802
+ .ui-color-picker-presets-color[data-selected] {
803
+ box-shadow:
804
+ 0 0 0 var(--stroke-md) hsl(var(--background)),
805
+ 0 0 0 calc(var(--stroke-md) * 2) hsl(var(--foreground));
806
+ }
807
+
808
+ .ui-color-picker-presets-color[data-disabled] {
809
+ cursor: not-allowed;
810
+ opacity: var(--disabled-opacity);
811
+ }
812
+
813
+ .ui-color-picker-presets-empty {
814
+ display: block;
815
+ padding-block: var(--space-1);
816
+ color: hsl(var(--muted-foreground));
817
+ font-size: var(--color-picker-presets-font-size);
818
+ }
819
+
741
820
  .ui-query-refetch-icon[data-fetching="true"] {
742
821
  animation: spin 1s linear infinite;
743
822
  }
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "31.7.0",
2
+ "version": "31.8.0",
3
3
  "generatedBy": "scripts/gen-style-layers.mjs — do not edit by hand; run `pnpm gen:style-layers`",
4
4
  "base": "base.css",
5
5
  "fonts": "fonts.css",
@@ -157,6 +157,10 @@
157
157
 
158
158
  --color-picker-input-width: 6.5rem;
159
159
 
160
+ --color-picker-preset-size: var(--touch-target-min);
161
+ --color-picker-preset-gap: var(--space-2);
162
+ --color-picker-presets-gap: var(--space-1);
163
+
160
164
  --command-list-max-height: min(300px, 50vh);
161
165
  --command-input-padding-x: var(--space-3);
162
166
  --command-group-padding: var(--space-1);
@@ -192,6 +196,10 @@
192
196
  --font-size-xs,
193
197
  calc(var(--font-size-base) / var(--font-size-ratio))
194
198
  );
199
+ --color-picker-presets-font-size: var(
200
+ --font-size-xs,
201
+ calc(var(--font-size-base) / var(--font-size-ratio))
202
+ );
195
203
  --command-group-heading-font-size: var(
196
204
  --font-size-xs,
197
205
  calc(var(--font-size-base) / var(--font-size-ratio))
@@ -3,19 +3,33 @@ import { useState } from "react";
3
3
  import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@godxjp/ui/data-display";
4
4
  import { ColorPicker, FormField } from "@godxjp/ui/data-entry";
5
5
  import { Text } from "@godxjp/ui/general";
6
+ import { useTranslation } from "@godxjp/ui/i18n";
6
7
  import { Flex, PageContainer } from "@godxjp/ui/layout";
7
8
 
9
+ /** A fixed tag palette (gh#1055): tags pick from it, never from free hex. */
10
+ const TAG_PALETTE = ["#dc2626", "#ea580c", "#ca8a04", "#16a34a", "#0891b2", "#2563eb", "#9333ea"];
11
+
8
12
  /**
9
13
  * ColorPicker — hex color swatch + optional editable hex input.
10
14
  * Always initialize state to a valid 3- or 6-digit hex string.
11
15
  * Use controlled mode (value + onValueChange); no uncontrolled path.
12
16
  * Composed only from real @godxjp/ui components.
17
+ *
18
+ * `presets` / `panelRender` port antd ColorPicker (gh#1055). Deviations from antd, on purpose:
19
+ * - `colors` are hex strings only — the value is hex; antd also takes colour objects/gradients.
20
+ * - There is no popover: the picker is inline, so `panelRender` replaces the inline body. The
21
+ * presets-only recipe is antd's own: `panelRender={(_, { components: { Presets } }) => <Presets />}`.
22
+ * - Each swatch is a real radio (APG radio group, named by its hex, arrow keys select); antd's
23
+ * preset blocks are click-only divs.
13
24
  */
14
25
  export default function Demo() {
15
26
  const [brandColor, setBrandColor] = useState("#2563eb");
16
27
  const [accentColor, setAccentColor] = useState("#16a34a");
17
28
  const [categoryColor, setCategoryColor] = useState("#dc2626");
18
29
  const [validatedColor, setValidatedColor] = useState("#9333ea");
30
+ const [labelColor, setLabelColor] = useState("#16a34a");
31
+ const [tagColor, setTagColor] = useState("#2563eb");
32
+ const { t } = useTranslation();
19
33
 
20
34
  return (
21
35
  <PageContainer title="ColorPicker" subtitle="カラーピッカー · スウォッチ+Hex入力">
@@ -75,6 +89,64 @@ export default function Demo() {
75
89
  </CardContent>
76
90
  </Card>
77
91
 
92
+ <Card>
93
+ <CardHeader>
94
+ <CardTitle level={2}>{t("showcase.colorPicker.presetsTitle")}</CardTitle>
95
+ <CardDescription>{t("showcase.colorPicker.presetsDescription")}</CardDescription>
96
+ </CardHeader>
97
+ <CardContent>
98
+ <FormField id="label-color" label={t("showcase.colorPicker.paletteLabel")}>
99
+ <ColorPicker
100
+ id="label-color"
101
+ value={labelColor}
102
+ onValueChange={setLabelColor}
103
+ presets={[
104
+ {
105
+ key: "recommended",
106
+ label: t("showcase.colorPicker.recommendedGroup"),
107
+ colors: TAG_PALETTE,
108
+ },
109
+ {
110
+ key: "recent",
111
+ label: t("showcase.colorPicker.recentGroup"),
112
+ colors: ["#2563eb", "#16a34a"],
113
+ defaultOpen: false,
114
+ },
115
+ ]}
116
+ />
117
+ </FormField>
118
+ </CardContent>
119
+ </Card>
120
+
121
+ <Card>
122
+ <CardHeader>
123
+ <CardTitle level={2}>{t("showcase.colorPicker.presetsOnlyTitle")}</CardTitle>
124
+ <CardDescription>{t("showcase.colorPicker.presetsOnlyDescription")}</CardDescription>
125
+ </CardHeader>
126
+ <CardContent>
127
+ <FormField
128
+ id="tag-color"
129
+ label={t("showcase.colorPicker.tagColorLabel")}
130
+ helper={t("showcase.colorPicker.tagColorHelper")}
131
+ >
132
+ <ColorPicker
133
+ id="tag-color"
134
+ name="tag_color"
135
+ value={tagColor}
136
+ onValueChange={setTagColor}
137
+ presets={[
138
+ {
139
+ key: "tags",
140
+ label: t("showcase.colorPicker.recommendedGroup"),
141
+ colors: TAG_PALETTE,
142
+ },
143
+ ]}
144
+ panelRender={(_, { components: { Presets } }) => <Presets />}
145
+ />
146
+ </FormField>
147
+ </CardContent>
148
+ </Card>
149
+
78
150
  <Card>
79
151
  <CardHeader>
80
152
  <CardTitle level={2}>Hex バリデーションと確定動作</CardTitle>
@@ -23,6 +23,7 @@ import {
23
23
  SelectValue,
24
24
  } from "@godxjp/ui/data-entry";
25
25
  import { Button } from "@godxjp/ui/general";
26
+ import { useTranslation } from "@godxjp/ui/i18n";
26
27
  import { Flex, PageContainer } from "@godxjp/ui/layout";
27
28
  import { X } from "lucide-react";
28
29
 
@@ -32,6 +33,7 @@ import { X } from "lucide-react";
32
33
  * trigger. Never a raw <select>. Composed only from real @godxjp/ui components.
33
34
  */
34
35
  export default function Demo() {
36
+ const { t, locale } = useTranslation();
35
37
  const [status, setStatus] = useState("paid");
36
38
  const [currency, setCurrency] = useState("JPY");
37
39
  const [priority, setPriority] = useState("medium");
@@ -43,6 +45,8 @@ export default function Demo() {
43
45
  const [reviewerLabel, setReviewerLabel] = useState("tanaka");
44
46
  const [prefixed, setPrefixed] = useState("JPY");
45
47
  const [tags, setTags] = useState<string[]>(["至急", "社内便"]);
48
+ const [labels, setLabels] = useState<string[]>([]);
49
+ const [created, setCreated] = useState<string[]>([]);
46
50
  // antd `labelInValue`: the record arrives carrying its own label, before any option list loads.
47
51
  const [assignedTo, setAssignedTo] = useState<
48
52
  { value: string; label: React.ReactNode } | undefined
@@ -481,6 +485,40 @@ export default function Demo() {
481
485
  </CardContent>
482
486
  </Card>
483
487
 
488
+ <Card>
489
+ <CardHeader>
490
+ <CardTitle level={2}>{t("showcase.select.createTitle")}</CardTitle>
491
+ <CardDescription>{t("showcase.select.createDescription")}</CardDescription>
492
+ </CardHeader>
493
+ <CardContent>
494
+ <FormField
495
+ id="issue-labels"
496
+ label={t("showcase.select.createField")}
497
+ helper={
498
+ created.length
499
+ ? t("showcase.select.createdHelper", {
500
+ list: new Intl.ListFormat(locale).format(created),
501
+ })
502
+ : t("showcase.select.createdNone")
503
+ }
504
+ >
505
+ <Select
506
+ id="issue-labels"
507
+ mode="tags"
508
+ value={labels}
509
+ onValueChange={setLabels}
510
+ onCreate={(text) => setCreated((previous) => [...previous, text])}
511
+ allowCreate={(text) => text.length <= 12}
512
+ options={[
513
+ { value: "bug", label: "Bug" },
514
+ { value: "feature", label: "Feature" },
515
+ { value: "docs", label: "Docs" },
516
+ ]}
517
+ />
518
+ </FormField>
519
+ </CardContent>
520
+ </Card>
521
+
484
522
  <Card>
485
523
  <CardHeader>
486
524
  <CardTitle level={2}>labelInValue · 読み込み前でも名前が出る</CardTitle>
@@ -543,6 +543,24 @@
543
543
  "longIdTitle": "Long identifiers and +N",
544
544
  "ledgerLabel": "Ledger ID",
545
545
  "ledgerHelper": "A 71-character identifier still stays inside the control"
546
+ },
547
+ "select": {
548
+ "createTitle": "Tags: create row, onCreate and case-insensitive matching",
549
+ "createDescription": "Typed text that matches no option is offered as an explicit “Create” row. onCreate reports only invented text, never an option id. Typing “bug” finds “Bug” instead of creating a duplicate (caseSensitive restores exact matching). Unlike antd, the create row is labelled and text longer than 12 characters is refused through allowCreate.",
550
+ "createField": "Labels",
551
+ "createdHelper": "Created in this session: {list}",
552
+ "createdNone": "Nothing created yet"
553
+ },
554
+ "colorPicker": {
555
+ "presetsTitle": "Tag colour from a palette",
556
+ "presetsDescription": "presets — fixed swatch groups under the picker; each group collapses, and the free picker stays available.",
557
+ "paletteLabel": "Label colour",
558
+ "recommendedGroup": "Recommended",
559
+ "recentGroup": "Recently used",
560
+ "presetsOnlyTitle": "Palette only",
561
+ "presetsOnlyDescription": "panelRender returns only Presets — people pick from the palette and cannot type an arbitrary hex.",
562
+ "tagColorLabel": "Tag colour",
563
+ "tagColorHelper": "Arrow keys move between swatches; the selected one is announced."
546
564
  }
547
565
  },
548
566
  "serviceLauncherShowcase": {
@@ -537,6 +537,24 @@
537
537
  "longIdTitle": "長い識別子と「+N」",
538
538
  "ledgerLabel": "台帳ID",
539
539
  "ledgerHelper": "71文字の識別子でも行からはみ出さない"
540
+ },
541
+ "select": {
542
+ "createTitle": "タグ: 作成行・onCreate・大文字小文字を区別しない照合",
543
+ "createDescription": "どの選択肢にも一致しない入力は「作成」行として明示されます。onCreate は新しく作られたテキストだけを通知し、選択肢の ID では発火しません。「bug」と入力すると「Bug」が見つかり、重複は作られません(caseSensitive で完全一致に戻せます)。antd と異なり作成行にはラベルが付き、12 文字を超える入力は allowCreate で拒否しています。",
544
+ "createField": "ラベル",
545
+ "createdHelper": "このセッションで作成: {list}",
546
+ "createdNone": "まだ作成されていません"
547
+ },
548
+ "colorPicker": {
549
+ "presetsTitle": "パレットからタグの色を選ぶ",
550
+ "presetsDescription": "presets — ピッカーの下に固定スウォッチのグループを表示。グループは折りたためて、自由入力も残る。",
551
+ "paletteLabel": "ラベルの色",
552
+ "recommendedGroup": "おすすめ",
553
+ "recentGroup": "最近使った色",
554
+ "presetsOnlyTitle": "パレットのみ",
555
+ "presetsOnlyDescription": "panelRender で Presets だけを返すと、パレットからの選択のみになり任意の HEX は入力できない。",
556
+ "tagColorLabel": "タグの色",
557
+ "tagColorHelper": "矢印キーでスウォッチ間を移動し、選択中の色が読み上げられる。"
540
558
  }
541
559
  },
542
560
  "serviceLauncherShowcase": {
@@ -537,6 +537,24 @@
537
537
  "longIdTitle": "Định danh dài và +N",
538
538
  "ledgerLabel": "Mã sổ cái",
539
539
  "ledgerHelper": "Định danh 71 ký tự vẫn nằm trong khung"
540
+ },
541
+ "select": {
542
+ "createTitle": "Tags: dòng tạo mới, onCreate và so khớp không phân biệt hoa thường",
543
+ "createDescription": "Văn bản gõ vào không khớp tùy chọn nào được đưa ra thành dòng “Tạo” rõ ràng. onCreate chỉ báo văn bản mới tạo, không bao giờ báo id của tùy chọn. Gõ “bug” sẽ tìm thấy “Bug” thay vì tạo bản trùng (caseSensitive trả lại so khớp chính xác). Khác antd, dòng tạo có nhãn và văn bản dài hơn 12 ký tự bị allowCreate từ chối.",
544
+ "createField": "Nhãn",
545
+ "createdHelper": "Đã tạo trong phiên này: {list}",
546
+ "createdNone": "Chưa tạo gì"
547
+ },
548
+ "colorPicker": {
549
+ "presetsTitle": "Màu thẻ chọn từ bảng màu",
550
+ "presetsDescription": "presets — các nhóm ô màu cố định dưới bộ chọn; mỗi nhóm thu gọn được, bộ chọn tự do vẫn còn.",
551
+ "paletteLabel": "Màu nhãn",
552
+ "recommendedGroup": "Đề xuất",
553
+ "recentGroup": "Dùng gần đây",
554
+ "presetsOnlyTitle": "Chỉ bảng màu",
555
+ "presetsOnlyDescription": "panelRender chỉ trả về Presets — người dùng chọn trong bảng màu, không gõ được mã hex tuỳ ý.",
556
+ "tagColorLabel": "Màu thẻ",
557
+ "tagColorHelper": "Phím mũi tên di chuyển giữa các ô màu; ô đang chọn được đọc lên."
540
558
  }
541
559
  },
542
560
  "serviceLauncherShowcase": {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@godxjp/ui",
3
- "version": "31.7.0",
4
- "godxUiMcp": "31.7.0",
3
+ "version": "31.8.0",
4
+ "godxUiMcp": "31.8.0",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
7
7
  "type": "git",