@godxjp/ui 30.4.2 → 30.5.3
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/agent/START-HERE.md +6 -6
- package/agent/components/Carousel.json +4 -1
- package/agent/components/RecordPicker.json +108 -0
- package/agent/components/ResponsiveGrid.json +3 -1
- package/agent/components/Reveal.json +6 -1
- package/agent/components/Table.json +6 -0
- package/agent/components/Text.json +8 -0
- package/agent/components-index.json +5 -0
- package/agent/components.json +135 -3
- package/agent/index.json +7 -7
- package/agent/llms.txt +7 -7
- package/agent/patterns/brand-theme-block.json +33 -0
- package/agent/patterns-index.json +32 -0
- package/agent/patterns.json +33 -0
- package/agent/tokens.json +12 -0
- package/dist/components/data-display/table.d.ts +30 -1
- package/dist/components/data-display/table.js +2 -1
- package/dist/components/data-entry/index.d.ts +2 -0
- package/dist/components/data-entry/index.js +2 -0
- package/dist/components/data-entry/record-picker.d.ts +63 -0
- package/dist/components/data-entry/record-picker.js +359 -0
- package/dist/components/general/typography.d.ts +1 -0
- package/dist/components/general/typography.js +10 -0
- package/dist/contracts/measurement.json +1 -1
- package/dist/i18n/messages/en.json +18 -0
- package/dist/i18n/messages/ja.json +18 -0
- package/dist/i18n/messages/vi.json +18 -0
- package/dist/props/components/data-entry.prop.d.ts +64 -0
- package/dist/props/components/general.prop.d.ts +15 -1
- package/dist/props/registry.d.ts +17 -0
- package/dist/props/registry.js +17 -0
- package/dist/props/vocabulary/index.d.ts +1 -1
- package/dist/props/vocabulary/interaction.prop.d.ts +13 -0
- package/dist/styles/data-display-layout.css +6 -3
- package/dist/styles/data-entry-layout.css +82 -0
- package/dist/styles/dialog-layout.css +8 -0
- package/dist/styles/focus-ring.css +2 -0
- package/dist/styles/table-layout.css +13 -0
- package/dist/styles/text-layout.css +8 -0
- package/dist/tokens/components/data-display.css +2 -0
- package/dist/tokens/components/data-entry.css +3 -0
- package/docs/FRAME-COVERAGE-REPORT.md +3 -2
- package/docs/assets/tcgm/card-1.svg +1 -0
- package/docs/assets/tcgm/card-2.svg +1 -0
- package/docs/assets/tcgm/card-3.svg +1 -0
- package/docs/assets/tcgm/card-4.svg +1 -0
- package/docs/assets/tcgm/card-5.svg +1 -0
- package/docs/assets/tcgm/card-6.svg +1 -0
- package/docs/assets/tcgm/hero-prism.svg +1 -0
- package/docs/assets/tcgm/scene-1.svg +1 -0
- package/docs/assets/tcgm/scene-2.svg +1 -0
- package/docs/assets/tcgm/scene-3.svg +1 -0
- package/docs/assets/tcgm/scene-4.svg +1 -0
- package/docs/assets/tcgm/scene-5.svg +1 -0
- package/docs/assets/tcgm/tcgm-lockup-color.svg +1 -0
- package/docs/assets/tcgm/tcgm-symbol-color.svg +1 -0
- package/docs/data-entry/record-picker.tsx +208 -0
- package/docs/general/typography.tsx +28 -0
- package/docs/i18n/messages/en.json +185 -1
- package/docs/i18n/messages/ja.json +185 -1
- package/docs/i18n/messages/vi.json +185 -1
- package/docs/showcase/tcgm-website.tsx +1047 -0
- package/package.json +3 -3
- package/scripts/ui-audit.mjs +23 -0
|
@@ -96,6 +96,19 @@ export type TextAlignProp = "start" | "center" | "end";
|
|
|
96
96
|
* remaining CSS keywords (`pre`, `pre-line`, `nowrap`) are values on the same axis, not more flags.
|
|
97
97
|
*/
|
|
98
98
|
export type TextWhitespaceProp = "normal" | "pre-wrap";
|
|
99
|
+
/**
|
|
100
|
+
* Where a run of text may break an over-long token that has no break opportunity of its own — an
|
|
101
|
+
* email address, a coupon code, a login id, a template key (gh#927).
|
|
102
|
+
*
|
|
103
|
+
* `normal` is CSS's own behaviour and the default: an unbroken token stays whole and overflows.
|
|
104
|
+
*
|
|
105
|
+
* `anywhere` is `overflow-wrap: anywhere`. It is a SEPARATE axis from {@link TextWhitespaceProp}
|
|
106
|
+
* because the two answer different questions: `whitespace` says whether the line breaks a person
|
|
107
|
+
* typed are content, `break` says whether a machine identifier may be split to fit. Only `anywhere`
|
|
108
|
+
* — not `break-word` — lowers the box's min-content size (CSS Text 3 §5.5), which is what a table
|
|
109
|
+
* cell sizes its column from; `break-word` breaks in a block and still holds a `<td>` open.
|
|
110
|
+
*/
|
|
111
|
+
export type TextBreakProp = "normal" | "anywhere";
|
|
99
112
|
/**
|
|
100
113
|
* antd `Typography` `type` — its four-value emphasis axis (`BaseType`).
|
|
101
114
|
*
|
|
@@ -657,7 +657,9 @@
|
|
|
657
657
|
|
|
658
658
|
.ui-carousel-item {
|
|
659
659
|
position: relative;
|
|
660
|
-
|
|
660
|
+
flex-shrink: 0;
|
|
661
|
+
inline-size: 100%;
|
|
662
|
+
min-inline-size: 0;
|
|
661
663
|
padding-inline: var(--space-4);
|
|
662
664
|
}
|
|
663
665
|
|
|
@@ -675,8 +677,9 @@
|
|
|
675
677
|
);
|
|
676
678
|
z-index: 20;
|
|
677
679
|
display: grid;
|
|
678
|
-
|
|
679
|
-
|
|
680
|
+
|
|
681
|
+
inline-size: var(--carousel-arrow-size);
|
|
682
|
+
block-size: var(--carousel-arrow-size);
|
|
680
683
|
place-items: center;
|
|
681
684
|
border-radius: var(--radius-pill);
|
|
682
685
|
background: hsl(var(--background));
|
|
@@ -764,3 +764,85 @@
|
|
|
764
764
|
text-align: start;
|
|
765
765
|
}
|
|
766
766
|
}
|
|
767
|
+
|
|
768
|
+
@layer components {
|
|
769
|
+
|
|
770
|
+
.ui-record-picker-trigger {
|
|
771
|
+
justify-content: space-between;
|
|
772
|
+
inline-size: 100%;
|
|
773
|
+
min-block-size: var(--control-height);
|
|
774
|
+
block-size: auto;
|
|
775
|
+
padding-block: var(--space-1);
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
.ui-record-picker-trigger-label {
|
|
779
|
+
display: flex;
|
|
780
|
+
flex: 1 1 auto;
|
|
781
|
+
min-inline-size: 0;
|
|
782
|
+
text-align: start;
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
.ui-record-picker-list {
|
|
786
|
+
max-block-size: var(--record-picker-list-max-block-size);
|
|
787
|
+
overflow-y: auto;
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
.ui-record-picker-option {
|
|
791
|
+
display: flex;
|
|
792
|
+
inline-size: 100%;
|
|
793
|
+
align-items: center;
|
|
794
|
+
gap: var(--space-2);
|
|
795
|
+
padding: var(--space-2) var(--space-3);
|
|
796
|
+
border-radius: var(--radius-md);
|
|
797
|
+
text-align: start;
|
|
798
|
+
color: inherit;
|
|
799
|
+
}
|
|
800
|
+
.ui-record-picker-option:disabled {
|
|
801
|
+
opacity: var(--disabled-opacity);
|
|
802
|
+
cursor: not-allowed;
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
@media (hover: hover) {
|
|
806
|
+
.ui-record-picker-option:hover {
|
|
807
|
+
background-color: hsl(var(--accent));
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
.ui-record-picker-option[data-picked] {
|
|
811
|
+
color: hsl(var(--text-brand, var(--primary)));
|
|
812
|
+
font-weight: var(--font-weight-medium);
|
|
813
|
+
}
|
|
814
|
+
.ui-record-picker-tick {
|
|
815
|
+
display: grid;
|
|
816
|
+
place-items: center;
|
|
817
|
+
inline-size: var(--icon-size-md);
|
|
818
|
+
block-size: var(--icon-size-md);
|
|
819
|
+
flex: 0 0 auto;
|
|
820
|
+
}
|
|
821
|
+
.ui-record-picker-tick svg {
|
|
822
|
+
inline-size: var(--icon-size-md);
|
|
823
|
+
block-size: var(--icon-size-md);
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
.ui-record-picker-option-label {
|
|
827
|
+
display: flex;
|
|
828
|
+
flex-direction: column;
|
|
829
|
+
min-inline-size: 0;
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
.ui-record-picker-status {
|
|
833
|
+
padding: var(--space-4);
|
|
834
|
+
color: hsl(var(--muted-foreground));
|
|
835
|
+
font-size: var(--font-size-sm);
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
@layer components {
|
|
840
|
+
|
|
841
|
+
.ui-record-picker-row {
|
|
842
|
+
inline-size: 100%;
|
|
843
|
+
}
|
|
844
|
+
.ui-record-picker-row > .ui-record-picker-trigger {
|
|
845
|
+
flex: 1 1 auto;
|
|
846
|
+
min-inline-size: 0;
|
|
847
|
+
}
|
|
848
|
+
}
|
|
@@ -285,6 +285,14 @@
|
|
|
285
285
|
}
|
|
286
286
|
}
|
|
287
287
|
|
|
288
|
+
[data-slot="popover-content"][data-state="closed"],
|
|
289
|
+
[data-slot="dropdown-menu-content"][data-state="closed"],
|
|
290
|
+
[data-slot="dropdown-menu-sub-content"][data-state="closed"],
|
|
291
|
+
[data-slot="hover-card-content"][data-state="closed"],
|
|
292
|
+
[data-slot="tooltip-content"][data-state="closed"] {
|
|
293
|
+
pointer-events: none;
|
|
294
|
+
}
|
|
295
|
+
|
|
288
296
|
@layer components {
|
|
289
297
|
|
|
290
298
|
.ui-tooltip-content {
|
|
@@ -15,6 +15,19 @@
|
|
|
15
15
|
border-block-end-width: 0;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
.ui-table-row[data-interactive] {
|
|
19
|
+
cursor: pointer;
|
|
20
|
+
}
|
|
21
|
+
@media (hover: hover) {
|
|
22
|
+
.ui-table-row[data-interactive]:hover {
|
|
23
|
+
background-color: color-mix(
|
|
24
|
+
in oklab,
|
|
25
|
+
hsl(var(--accent)) var(--table-row-hover-background-alpha, 70%),
|
|
26
|
+
transparent
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
18
31
|
.ui-table-row[data-tone="primary"] {
|
|
19
32
|
--table-row-tone-color: var(
|
|
20
33
|
--mark-primary,
|
|
@@ -161,6 +161,14 @@
|
|
|
161
161
|
min-inline-size: 0;
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
+
[data-slot="text"][data-break="anywhere"] {
|
|
165
|
+
overflow-wrap: anywhere;
|
|
166
|
+
min-inline-size: 0;
|
|
167
|
+
}
|
|
168
|
+
[data-slot="text"][data-break="anywhere"]:not([data-whitespace]) {
|
|
169
|
+
white-space: normal;
|
|
170
|
+
}
|
|
171
|
+
|
|
164
172
|
[data-slot="text"][data-clamp] {
|
|
165
173
|
display: -webkit-box;
|
|
166
174
|
-webkit-box-orient: vertical;
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
> Generated by `scripts/frame-coverage.mjs` (issue #163). Do not edit by hand — run `pnpm check:frame-coverage`.
|
|
4
4
|
> Standard: [FRAME-COVERAGE-STANDARD.md](./FRAME-COVERAGE-STANDARD.md). A missing dimension is **UNTESTED**, never a pass.
|
|
5
5
|
|
|
6
|
-
- Public components: **
|
|
7
|
-
- With ≥1 frame: **
|
|
6
|
+
- Public components: **173**
|
|
7
|
+
- With ≥1 frame: **152** · zero-frame: **21**
|
|
8
8
|
- Fully covered (every contract axis declared): **0**
|
|
9
9
|
|
|
10
10
|
## UNTESTED — no `/frame/**` route
|
|
@@ -106,6 +106,7 @@ Legend: ✓ covered · N/A reasoned skip · · UNTESTED (blank cell = UNTESTED).
|
|
|
106
106
|
| Input | ✓ | ✓ | · | · | · | · | · | · | · | · |
|
|
107
107
|
| NumberInput | ✓ | ✓ | · | · | · | · | · | · | · | · |
|
|
108
108
|
| SearchInput | ✓ | ✓ | · | · | · | · | · | · | · | · |
|
|
109
|
+
| RecordPicker | ✓ | · | · | · | · | · | · | · | · | · |
|
|
109
110
|
| Select | ✓ | · | · | · | · | · | · | · | · | · |
|
|
110
111
|
| Switch | ✓ | ✓ | · | · | · | · | · | · | · | · |
|
|
111
112
|
| Textarea | ✓ | ✓ | · | · | · | · | · | · | · | · |
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="630" height="880" viewBox="0 0 630 880" role="img"><title>Fictional TCG-M demo card; no real game affiliation</title><defs><linearGradient id="s0" x2="0" y2="1"><stop stop-color="#DFF3FF"/><stop offset="1" stop-color="#BDCAFB"/></linearGradient><linearGradient id="r0" x2="0" y2="1"><stop stop-color="white" stop-opacity=".85"/><stop offset="1" stop-color="white" stop-opacity="0"/></linearGradient></defs><rect width="630" height="880" rx="38" fill="#FFFFFF"/><g transform="translate(22 22) scale(.93)"><rect width="630" height="880" fill="url(#s0)"/><circle cx="410" cy="215" r="115" fill="white" opacity=".65"/><path d="M0 450 138 218 318 472 470 310 630 482V880H0Z" fill="#486F95" opacity=".35"/><path d="M0 609 164 357 343 580 475 398 630 548V880H0Z" fill="#486F95"/><path d="M0 712 190 516 346 720 466 560 630 690V880H0Z" fill="#0F4C5C"/><path d="M254 880Q474 696 322 658T286 528Q383 610 383 645T360 715Q347 783 405 880Z" fill="url(#r0)"/><path d="M106 119h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M323 101h10m-5 -5v10" stroke="white" stroke-width="3"/><path d="M528 285h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M209 282h6m-3 -3v6" stroke="white" stroke-width="3"/><path d="M551 93h6m-3 -3v6" stroke="white" stroke-width="3"/></g><rect x="36" y="672" width="558" height="170" rx="20" fill="#FFFFFF" fill-opacity=".94"/><text x="60" y="718" fill="#0F4C5C" font-family="Arial,sans-serif" font-size="22" letter-spacing="4">TCG-M / SAMPLE</text><text x="60" y="775" fill="#0F4C5C" font-family="Arial,sans-serif" font-size="36" font-weight="700">PRISM WORLD 01</text><text x="60" y="815" fill="#526A73" font-family="Arial,sans-serif" font-size="20">FICTIONAL DESIGN ASSET</text></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="630" height="880" viewBox="0 0 630 880" role="img"><title>Fictional TCG-M demo card; no real game affiliation</title><defs><linearGradient id="s1" x2="0" y2="1"><stop stop-color="#FFF2E7"/><stop offset="1" stop-color="#FFCED1"/></linearGradient><linearGradient id="r1" x2="0" y2="1"><stop stop-color="white" stop-opacity=".85"/><stop offset="1" stop-color="white" stop-opacity="0"/></linearGradient></defs><rect width="630" height="880" rx="38" fill="#FFFFFF"/><g transform="translate(22 22) scale(.93)"><rect width="630" height="880" fill="url(#s1)"/><circle cx="391" cy="215" r="115" fill="white" opacity=".65"/><path d="M0 450 138 218 318 472 470 310 630 482V880H0Z" fill="#AA7BA9" opacity=".35"/><path d="M0 609 164 357 343 580 475 398 630 548V880H0Z" fill="#AA7BA9"/><path d="M0 712 190 516 346 720 466 560 630 690V880H0Z" fill="#625582"/><path d="M254 880Q474 696 322 658T286 528Q383 610 383 645T360 715Q347 783 405 880Z" fill="url(#r1)"/><path d="M106 119h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M323 101h10m-5 -5v10" stroke="white" stroke-width="3"/><path d="M528 285h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M209 282h6m-3 -3v6" stroke="white" stroke-width="3"/><path d="M551 93h6m-3 -3v6" stroke="white" stroke-width="3"/></g><rect x="36" y="672" width="558" height="170" rx="20" fill="#FFFFFF" fill-opacity=".94"/><text x="60" y="718" fill="#0F4C5C" font-family="Arial,sans-serif" font-size="22" letter-spacing="4">TCG-M / SAMPLE</text><text x="60" y="775" fill="#0F4C5C" font-family="Arial,sans-serif" font-size="36" font-weight="700">PRISM WORLD 02</text><text x="60" y="815" fill="#526A73" font-family="Arial,sans-serif" font-size="20">FICTIONAL DESIGN ASSET</text></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="630" height="880" viewBox="0 0 630 880" role="img"><title>Fictional TCG-M demo card; no real game affiliation</title><defs><linearGradient id="s2" x2="0" y2="1"><stop stop-color="#E5F6F0"/><stop offset="1" stop-color="#BDE7E5"/></linearGradient><linearGradient id="r2" x2="0" y2="1"><stop stop-color="white" stop-opacity=".85"/><stop offset="1" stop-color="white" stop-opacity="0"/></linearGradient></defs><rect width="630" height="880" rx="38" fill="#FFFFFF"/><g transform="translate(22 22) scale(.93)"><rect width="630" height="880" fill="url(#s2)"/><circle cx="372" cy="215" r="115" fill="white" opacity=".65"/><path d="M0 450 138 218 318 472 470 310 630 482V880H0Z" fill="#65AAA7" opacity=".35"/><path d="M0 609 164 357 343 580 475 398 630 548V880H0Z" fill="#65AAA7"/><path d="M0 712 190 516 346 720 466 560 630 690V880H0Z" fill="#326B71"/><path d="M254 880Q474 696 322 658T286 528Q383 610 383 645T360 715Q347 783 405 880Z" fill="url(#r2)"/><path d="M106 119h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M323 101h10m-5 -5v10" stroke="white" stroke-width="3"/><path d="M528 285h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M209 282h6m-3 -3v6" stroke="white" stroke-width="3"/><path d="M551 93h6m-3 -3v6" stroke="white" stroke-width="3"/></g><rect x="36" y="672" width="558" height="170" rx="20" fill="#FFFFFF" fill-opacity=".94"/><text x="60" y="718" fill="#0F4C5C" font-family="Arial,sans-serif" font-size="22" letter-spacing="4">TCG-M / SAMPLE</text><text x="60" y="775" fill="#0F4C5C" font-family="Arial,sans-serif" font-size="36" font-weight="700">PRISM WORLD 03</text><text x="60" y="815" fill="#526A73" font-family="Arial,sans-serif" font-size="20">FICTIONAL DESIGN ASSET</text></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="630" height="880" viewBox="0 0 630 880" role="img"><title>Fictional TCG-M demo card; no real game affiliation</title><defs><linearGradient id="s3" x2="0" y2="1"><stop stop-color="#F2EAFF"/><stop offset="1" stop-color="#DCC4FD"/></linearGradient><linearGradient id="r3" x2="0" y2="1"><stop stop-color="white" stop-opacity=".85"/><stop offset="1" stop-color="white" stop-opacity="0"/></linearGradient></defs><rect width="630" height="880" rx="38" fill="#FFFFFF"/><g transform="translate(22 22) scale(.93)"><rect width="630" height="880" fill="url(#s3)"/><circle cx="353" cy="215" r="115" fill="white" opacity=".65"/><path d="M0 450 138 218 318 472 470 310 630 482V880H0Z" fill="#9784C7" opacity=".35"/><path d="M0 609 164 357 343 580 475 398 630 548V880H0Z" fill="#9784C7"/><path d="M0 712 190 516 346 720 466 560 630 690V880H0Z" fill="#57578D"/><path d="M254 880Q474 696 322 658T286 528Q383 610 383 645T360 715Q347 783 405 880Z" fill="url(#r3)"/><path d="M106 119h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M323 101h10m-5 -5v10" stroke="white" stroke-width="3"/><path d="M528 285h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M209 282h6m-3 -3v6" stroke="white" stroke-width="3"/><path d="M551 93h6m-3 -3v6" stroke="white" stroke-width="3"/></g><rect x="36" y="672" width="558" height="170" rx="20" fill="#FFFFFF" fill-opacity=".94"/><text x="60" y="718" fill="#0F4C5C" font-family="Arial,sans-serif" font-size="22" letter-spacing="4">TCG-M / SAMPLE</text><text x="60" y="775" fill="#0F4C5C" font-family="Arial,sans-serif" font-size="36" font-weight="700">PRISM WORLD 04</text><text x="60" y="815" fill="#526A73" font-family="Arial,sans-serif" font-size="20">FICTIONAL DESIGN ASSET</text></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="630" height="880" viewBox="0 0 630 880" role="img"><title>Fictional TCG-M demo card; no real game affiliation</title><defs><linearGradient id="s4" x2="0" y2="1"><stop stop-color="#FFF3CF"/><stop offset="1" stop-color="#F4D7BE"/></linearGradient><linearGradient id="r4" x2="0" y2="1"><stop stop-color="white" stop-opacity=".85"/><stop offset="1" stop-color="white" stop-opacity="0"/></linearGradient></defs><rect width="630" height="880" rx="38" fill="#FFFFFF"/><g transform="translate(22 22) scale(.93)"><rect width="630" height="880" fill="url(#s4)"/><circle cx="334" cy="215" r="115" fill="white" opacity=".65"/><path d="M0 450 138 218 318 472 470 310 630 482V880H0Z" fill="#B89599" opacity=".35"/><path d="M0 609 164 357 343 580 475 398 630 548V880H0Z" fill="#B89599"/><path d="M0 712 190 516 346 720 466 560 630 690V880H0Z" fill="#6E6883"/><path d="M254 880Q474 696 322 658T286 528Q383 610 383 645T360 715Q347 783 405 880Z" fill="url(#r4)"/><path d="M106 119h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M323 101h10m-5 -5v10" stroke="white" stroke-width="3"/><path d="M528 285h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M209 282h6m-3 -3v6" stroke="white" stroke-width="3"/><path d="M551 93h6m-3 -3v6" stroke="white" stroke-width="3"/></g><rect x="36" y="672" width="558" height="170" rx="20" fill="#FFFFFF" fill-opacity=".94"/><text x="60" y="718" fill="#0F4C5C" font-family="Arial,sans-serif" font-size="22" letter-spacing="4">TCG-M / SAMPLE</text><text x="60" y="775" fill="#0F4C5C" font-family="Arial,sans-serif" font-size="36" font-weight="700">PRISM WORLD 05</text><text x="60" y="815" fill="#526A73" font-family="Arial,sans-serif" font-size="20">FICTIONAL DESIGN ASSET</text></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="630" height="880" viewBox="0 0 630 880" role="img"><title>Fictional TCG-M demo card; no real game affiliation</title><defs><linearGradient id="s5" x2="0" y2="1"><stop stop-color="#E2EAFB"/><stop offset="1" stop-color="#B9D7ED"/></linearGradient><linearGradient id="r5" x2="0" y2="1"><stop stop-color="white" stop-opacity=".85"/><stop offset="1" stop-color="white" stop-opacity="0"/></linearGradient></defs><rect width="630" height="880" rx="38" fill="#FFFFFF"/><g transform="translate(22 22) scale(.93)"><rect width="630" height="880" fill="url(#s5)"/><circle cx="315" cy="215" r="115" fill="white" opacity=".65"/><path d="M0 450 138 218 318 472 470 310 630 482V880H0Z" fill="#597FAE" opacity=".35"/><path d="M0 609 164 357 343 580 475 398 630 548V880H0Z" fill="#597FAE"/><path d="M0 712 190 516 346 720 466 560 630 690V880H0Z" fill="#214D75"/><path d="M254 880Q474 696 322 658T286 528Q383 610 383 645T360 715Q347 783 405 880Z" fill="url(#r5)"/><path d="M106 119h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M323 101h10m-5 -5v10" stroke="white" stroke-width="3"/><path d="M528 285h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M209 282h6m-3 -3v6" stroke="white" stroke-width="3"/><path d="M551 93h6m-3 -3v6" stroke="white" stroke-width="3"/></g><rect x="36" y="672" width="558" height="170" rx="20" fill="#FFFFFF" fill-opacity=".94"/><text x="60" y="718" fill="#0F4C5C" font-family="Arial,sans-serif" font-size="22" letter-spacing="4">TCG-M / SAMPLE</text><text x="60" y="775" fill="#0F4C5C" font-family="Arial,sans-serif" font-size="36" font-weight="700">PRISM WORLD 06</text><text x="60" y="815" fill="#526A73" font-family="Arial,sans-serif" font-size="20">FICTIONAL DESIGN ASSET</text></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="760" viewBox="0 0 1200 760" role="img"><title>Layered Prism original decorative atmosphere</title><defs></defs><rect width="1200" height="760" fill="#F8FAFC"/><ellipse cx="900" cy="170" rx="560" ry="420" fill="#EAF7FF"/><ellipse cx="500" cy="790" rx="660" ry="380" fill="#F2EEFF"/><ellipse cx="1080" cy="650" rx="360" ry="310" fill="#FFF0EF"/><g transform="translate(390 150) rotate(-19 102.5 147.5)"><rect x="-8" y="-8" width="221" height="311" rx="20" fill="white"/><svg width="205" height="295" viewBox="0 0 630 880"><defs><linearGradient id="s1" x2="0" y2="1"><stop stop-color="#FFF2E7"/><stop offset="1" stop-color="#FFCED1"/></linearGradient><linearGradient id="r1" x2="0" y2="1"><stop stop-color="white" stop-opacity=".85"/><stop offset="1" stop-color="white" stop-opacity="0"/></linearGradient></defs><rect width="630" height="880" fill="url(#s1)"/><circle cx="391" cy="215" r="115" fill="white" opacity=".65"/><path d="M0 450 138 218 318 472 470 310 630 482V880H0Z" fill="#AA7BA9" opacity=".35"/><path d="M0 609 164 357 343 580 475 398 630 548V880H0Z" fill="#AA7BA9"/><path d="M0 712 190 516 346 720 466 560 630 690V880H0Z" fill="#625582"/><path d="M254 880Q474 696 322 658T286 528Q383 610 383 645T360 715Q347 783 405 880Z" fill="url(#r1)"/><path d="M106 119h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M323 101h10m-5 -5v10" stroke="white" stroke-width="3"/><path d="M528 285h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M209 282h6m-3 -3v6" stroke="white" stroke-width="3"/><path d="M551 93h6m-3 -3v6" stroke="white" stroke-width="3"/></svg></g><g transform="translate(640 110) rotate(11 132.5 190.0)"><rect x="-8" y="-8" width="281" height="396" rx="20" fill="white"/><svg width="265" height="380" viewBox="0 0 630 880"><defs><linearGradient id="s3" x2="0" y2="1"><stop stop-color="#F2EAFF"/><stop offset="1" stop-color="#DCC4FD"/></linearGradient><linearGradient id="r3" x2="0" y2="1"><stop stop-color="white" stop-opacity=".85"/><stop offset="1" stop-color="white" stop-opacity="0"/></linearGradient></defs><rect width="630" height="880" fill="url(#s3)"/><circle cx="353" cy="215" r="115" fill="white" opacity=".65"/><path d="M0 450 138 218 318 472 470 310 630 482V880H0Z" fill="#9784C7" opacity=".35"/><path d="M0 609 164 357 343 580 475 398 630 548V880H0Z" fill="#9784C7"/><path d="M0 712 190 516 346 720 466 560 630 690V880H0Z" fill="#57578D"/><path d="M254 880Q474 696 322 658T286 528Q383 610 383 645T360 715Q347 783 405 880Z" fill="url(#r3)"/><path d="M106 119h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M323 101h10m-5 -5v10" stroke="white" stroke-width="3"/><path d="M528 285h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M209 282h6m-3 -3v6" stroke="white" stroke-width="3"/><path d="M551 93h6m-3 -3v6" stroke="white" stroke-width="3"/></svg></g><g transform="translate(850 325) rotate(24 102.5 147.5)"><rect x="-8" y="-8" width="221" height="311" rx="20" fill="white"/><svg width="205" height="295" viewBox="0 0 630 880"><defs><linearGradient id="s2" x2="0" y2="1"><stop stop-color="#E5F6F0"/><stop offset="1" stop-color="#BDE7E5"/></linearGradient><linearGradient id="r2" x2="0" y2="1"><stop stop-color="white" stop-opacity=".85"/><stop offset="1" stop-color="white" stop-opacity="0"/></linearGradient></defs><rect width="630" height="880" fill="url(#s2)"/><circle cx="372" cy="215" r="115" fill="white" opacity=".65"/><path d="M0 450 138 218 318 472 470 310 630 482V880H0Z" fill="#65AAA7" opacity=".35"/><path d="M0 609 164 357 343 580 475 398 630 548V880H0Z" fill="#65AAA7"/><path d="M0 712 190 516 346 720 466 560 630 690V880H0Z" fill="#326B71"/><path d="M254 880Q474 696 322 658T286 528Q383 610 383 645T360 715Q347 783 405 880Z" fill="url(#r2)"/><path d="M106 119h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M323 101h10m-5 -5v10" stroke="white" stroke-width="3"/><path d="M528 285h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M209 282h6m-3 -3v6" stroke="white" stroke-width="3"/><path d="M551 93h6m-3 -3v6" stroke="white" stroke-width="3"/></svg></g><g stroke="#0F4C5C" stroke-opacity=".12" fill="none"><ellipse cx="740" cy="410" rx="420" ry="190" transform="rotate(-18 740 410)"/></g><path fill="#A78BFA" d="M350 416Q352 438 374 440Q352 442 350 464Q348 442 326 440Q348 438 350 416Z"/><path fill="#FF7B7B" d="M950 113Q952 138 977 140Q952 142 950 167Q948 142 923 140Q948 138 950 113Z"/><path fill="#38B6FF" d="M540 52Q542 68 558 70Q542 72 540 88Q538 72 522 70Q538 68 540 52Z"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="630" height="880" viewBox="0 0 630 880" role="img"><title>Original abstract landscape 1; not an actual game card</title><defs><linearGradient id="s0" x2="0" y2="1"><stop stop-color="#DFF3FF"/><stop offset="1" stop-color="#BDCAFB"/></linearGradient><linearGradient id="r0" x2="0" y2="1"><stop stop-color="white" stop-opacity=".85"/><stop offset="1" stop-color="white" stop-opacity="0"/></linearGradient></defs><rect width="630" height="880" fill="url(#s0)"/><circle cx="410" cy="215" r="115" fill="white" opacity=".65"/><path d="M0 450 138 218 318 472 470 310 630 482V880H0Z" fill="#486F95" opacity=".35"/><path d="M0 609 164 357 343 580 475 398 630 548V880H0Z" fill="#486F95"/><path d="M0 712 190 516 346 720 466 560 630 690V880H0Z" fill="#0F4C5C"/><path d="M254 880Q474 696 322 658T286 528Q383 610 383 645T360 715Q347 783 405 880Z" fill="url(#r0)"/><path d="M106 119h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M323 101h10m-5 -5v10" stroke="white" stroke-width="3"/><path d="M528 285h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M209 282h6m-3 -3v6" stroke="white" stroke-width="3"/><path d="M551 93h6m-3 -3v6" stroke="white" stroke-width="3"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="630" height="880" viewBox="0 0 630 880" role="img"><title>Original abstract landscape 2; not an actual game card</title><defs><linearGradient id="s1" x2="0" y2="1"><stop stop-color="#FFF2E7"/><stop offset="1" stop-color="#FFCED1"/></linearGradient><linearGradient id="r1" x2="0" y2="1"><stop stop-color="white" stop-opacity=".85"/><stop offset="1" stop-color="white" stop-opacity="0"/></linearGradient></defs><rect width="630" height="880" fill="url(#s1)"/><circle cx="391" cy="215" r="115" fill="white" opacity=".65"/><path d="M0 450 138 218 318 472 470 310 630 482V880H0Z" fill="#AA7BA9" opacity=".35"/><path d="M0 609 164 357 343 580 475 398 630 548V880H0Z" fill="#AA7BA9"/><path d="M0 712 190 516 346 720 466 560 630 690V880H0Z" fill="#625582"/><path d="M254 880Q474 696 322 658T286 528Q383 610 383 645T360 715Q347 783 405 880Z" fill="url(#r1)"/><path d="M106 119h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M323 101h10m-5 -5v10" stroke="white" stroke-width="3"/><path d="M528 285h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M209 282h6m-3 -3v6" stroke="white" stroke-width="3"/><path d="M551 93h6m-3 -3v6" stroke="white" stroke-width="3"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="630" height="880" viewBox="0 0 630 880" role="img"><title>Original abstract landscape 3; not an actual game card</title><defs><linearGradient id="s2" x2="0" y2="1"><stop stop-color="#E5F6F0"/><stop offset="1" stop-color="#BDE7E5"/></linearGradient><linearGradient id="r2" x2="0" y2="1"><stop stop-color="white" stop-opacity=".85"/><stop offset="1" stop-color="white" stop-opacity="0"/></linearGradient></defs><rect width="630" height="880" fill="url(#s2)"/><circle cx="372" cy="215" r="115" fill="white" opacity=".65"/><path d="M0 450 138 218 318 472 470 310 630 482V880H0Z" fill="#65AAA7" opacity=".35"/><path d="M0 609 164 357 343 580 475 398 630 548V880H0Z" fill="#65AAA7"/><path d="M0 712 190 516 346 720 466 560 630 690V880H0Z" fill="#326B71"/><path d="M254 880Q474 696 322 658T286 528Q383 610 383 645T360 715Q347 783 405 880Z" fill="url(#r2)"/><path d="M106 119h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M323 101h10m-5 -5v10" stroke="white" stroke-width="3"/><path d="M528 285h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M209 282h6m-3 -3v6" stroke="white" stroke-width="3"/><path d="M551 93h6m-3 -3v6" stroke="white" stroke-width="3"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="630" height="880" viewBox="0 0 630 880" role="img"><title>Original abstract landscape 4; not an actual game card</title><defs><linearGradient id="s3" x2="0" y2="1"><stop stop-color="#F2EAFF"/><stop offset="1" stop-color="#DCC4FD"/></linearGradient><linearGradient id="r3" x2="0" y2="1"><stop stop-color="white" stop-opacity=".85"/><stop offset="1" stop-color="white" stop-opacity="0"/></linearGradient></defs><rect width="630" height="880" fill="url(#s3)"/><circle cx="353" cy="215" r="115" fill="white" opacity=".65"/><path d="M0 450 138 218 318 472 470 310 630 482V880H0Z" fill="#9784C7" opacity=".35"/><path d="M0 609 164 357 343 580 475 398 630 548V880H0Z" fill="#9784C7"/><path d="M0 712 190 516 346 720 466 560 630 690V880H0Z" fill="#57578D"/><path d="M254 880Q474 696 322 658T286 528Q383 610 383 645T360 715Q347 783 405 880Z" fill="url(#r3)"/><path d="M106 119h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M323 101h10m-5 -5v10" stroke="white" stroke-width="3"/><path d="M528 285h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M209 282h6m-3 -3v6" stroke="white" stroke-width="3"/><path d="M551 93h6m-3 -3v6" stroke="white" stroke-width="3"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="630" height="880" viewBox="0 0 630 880" role="img"><title>Original abstract landscape 5; not an actual game card</title><defs><linearGradient id="s4" x2="0" y2="1"><stop stop-color="#FFF3CF"/><stop offset="1" stop-color="#F4D7BE"/></linearGradient><linearGradient id="r4" x2="0" y2="1"><stop stop-color="white" stop-opacity=".85"/><stop offset="1" stop-color="white" stop-opacity="0"/></linearGradient></defs><rect width="630" height="880" fill="url(#s4)"/><circle cx="334" cy="215" r="115" fill="white" opacity=".65"/><path d="M0 450 138 218 318 472 470 310 630 482V880H0Z" fill="#B89599" opacity=".35"/><path d="M0 609 164 357 343 580 475 398 630 548V880H0Z" fill="#B89599"/><path d="M0 712 190 516 346 720 466 560 630 690V880H0Z" fill="#6E6883"/><path d="M254 880Q474 696 322 658T286 528Q383 610 383 645T360 715Q347 783 405 880Z" fill="url(#r4)"/><path d="M106 119h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M323 101h10m-5 -5v10" stroke="white" stroke-width="3"/><path d="M528 285h8m-4 -4v8" stroke="white" stroke-width="3"/><path d="M209 282h6m-3 -3v6" stroke="white" stroke-width="3"/><path d="M551 93h6m-3 -3v6" stroke="white" stroke-width="3"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="510" height="150" viewBox="0 0 510 150" role="img"><title>TCG-M horizontal lockup / color</title><defs><linearGradient id="back" x1="0" y1="0" x2=".2" y2="1"><stop stop-color="#FF7B7B"/><stop offset="1" stop-color="#A78BFA"/></linearGradient><linearGradient id="rim" x1="0" y1="0" x2=".3" y2="1"><stop stop-color="#FFC66E"/><stop offset=".5" stop-color="#FF7B7B"/><stop offset="1" stop-color="#A78BFA"/></linearGradient><linearGradient id="left" x1="0" y1="0" x2="1" y2="1"><stop stop-color="#16819A"/><stop offset="1" stop-color="#0F4C5C"/></linearGradient><linearGradient id="right" x1="0" y1="0" x2="1" y2="1"><stop stop-color="#136E88"/><stop offset="1" stop-color="#0F4C5C"/></linearGradient><linearGradient id="spark" x1="0" y1="0" x2="0" y2="1"><stop stop-color="#A78BFA"/><stop offset=".5" stop-color="#FF7B7B"/><stop offset="1" stop-color="#FFC66E"/></linearGradient></defs><g transform="translate(0 0) scale(.55)"><path d="M31 67 Q22 64 25 78 L54 202 Q58 216 64 222 L45 69Z" fill="url(#back)"/><path d="M66 225 L55 68 Q54 53 66 49 L161 16 Q172 12 173 25 L173 31 L72 66Z" fill="url(#rim)"/><path d="M78 72 L181 36 Q192 32 192 45 L192 139 L151 174Z" fill="#38B6FF"/><path d="M204 53 L215 57 Q222 60 222 70 L222 109 L203 126Z" fill="url(#right)"/><path d="M76 87 L143 146 Q153 155 153 168 L153 188 Q153 197 145 191 L116 168 L116 219 L77 233 Q69 236 70 226Z" fill="url(#left)"/><path d="M167 167 Q168 155 177 146 L231 101 Q240 95 241 107 L241 203 L204 218 L204 168 L175 191 Q167 197 167 186Z" fill="url(#right)"/><path d="M161 167 C163 194 169 202 188 209 C169 214 164 221 161 244 C157 220 151 215 134 209 C152 204 157 195 161 167Z" fill="url(#spark)"/></g><g transform="translate(164 44) scale(.92)" fill="#0F4C5C"><path d="M0 0H63V15H40V73H23V15H0Z"/><path d="M138 5L132 22C124 17 119 15 112 15C95 15 86 24 86 37C86 51 96 59 111 59C120 59 126 56 133 51L140 66C131 72 121 76 110 76C84 76 67 60 67 37C67 15 84-2 111-2C122-2 131 0 138 5Z"/><path d="M215 7L206 21C198 16 192 14 183 14C169 14 159 23 159 37C159 50 169 60 183 60C189 60 194 59 199 56V46H181V32H216V65C208 72 195 76 182 76C158 76 142 60 142 37C142 14 159-2 183-2C196-2 207 1 215 7Z"/><path d="M228 31H258V45H228Z"/><path d="M271 0H288L311 32L334 0H351V73H334V28L311 60L288 28V73H271Z"/></g></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="264" height="264" viewBox="0 0 264 264" role="img"><title>TCG-M Layered Prism symbol / color</title><defs><linearGradient id="back" x1="0" y1="0" x2=".2" y2="1"><stop stop-color="#FF7B7B"/><stop offset="1" stop-color="#A78BFA"/></linearGradient><linearGradient id="rim" x1="0" y1="0" x2=".3" y2="1"><stop stop-color="#FFC66E"/><stop offset=".5" stop-color="#FF7B7B"/><stop offset="1" stop-color="#A78BFA"/></linearGradient><linearGradient id="left" x1="0" y1="0" x2="1" y2="1"><stop stop-color="#16819A"/><stop offset="1" stop-color="#0F4C5C"/></linearGradient><linearGradient id="right" x1="0" y1="0" x2="1" y2="1"><stop stop-color="#136E88"/><stop offset="1" stop-color="#0F4C5C"/></linearGradient><linearGradient id="spark" x1="0" y1="0" x2="0" y2="1"><stop stop-color="#A78BFA"/><stop offset=".5" stop-color="#FF7B7B"/><stop offset="1" stop-color="#FFC66E"/></linearGradient></defs><path d="M31 67 Q22 64 25 78 L54 202 Q58 216 64 222 L45 69Z" fill="url(#back)"/><path d="M66 225 L55 68 Q54 53 66 49 L161 16 Q172 12 173 25 L173 31 L72 66Z" fill="url(#rim)"/><path d="M78 72 L181 36 Q192 32 192 45 L192 139 L151 174Z" fill="#38B6FF"/><path d="M204 53 L215 57 Q222 60 222 70 L222 109 L203 126Z" fill="url(#right)"/><path d="M76 87 L143 146 Q153 155 153 168 L153 188 Q153 197 145 191 L116 168 L116 219 L77 233 Q69 236 70 226Z" fill="url(#left)"/><path d="M167 167 Q168 155 177 146 L231 101 Q240 95 241 107 L241 203 L204 218 L204 168 L175 191 Q167 197 167 186Z" fill="url(#right)"/><path d="M161 167 C163 194 169 202 188 209 C169 214 164 221 161 244 C157 220 151 215 134 209 C152 204 157 195 161 167Z" fill="url(#spark)"/></svg>
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
import { Shield, User } from "lucide-react";
|
|
3
|
+
|
|
4
|
+
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@godxjp/ui/data-display";
|
|
5
|
+
import { RecordPicker } from "@godxjp/ui/data-entry";
|
|
6
|
+
import { Icon, Text } from "@godxjp/ui/general";
|
|
7
|
+
import { Flex, PageContainer } from "@godxjp/ui/layout";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* RecordPicker — the three shapes a real consumer needed (gh#932).
|
|
11
|
+
*
|
|
12
|
+
* Every case on this page is one that shipped WRONG in an app before the component existed, and
|
|
13
|
+
* the page is arranged so the failure each one fixes is visible: a dropdown that cannot be
|
|
14
|
+
* searched, two kinds of thing in one field, and a free-text key that only failed validation
|
|
15
|
+
* after save.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
const SMALL = [
|
|
19
|
+
{ value: "u1", label: "Alex Tran" },
|
|
20
|
+
{ value: "u2", label: "Bea Nakamura" },
|
|
21
|
+
{ value: "u3", label: "Cam Ito" },
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
/** 800 people is the case the report is actually about; a dropdown cannot be the answer. */
|
|
25
|
+
const PEOPLE = Array.from({ length: 800 }, (_, i) => ({
|
|
26
|
+
value: `u${i}`,
|
|
27
|
+
label: `Member ${String(i).padStart(3, "0")}`,
|
|
28
|
+
sublabel: `member${i}@example.co.jp`,
|
|
29
|
+
}));
|
|
30
|
+
|
|
31
|
+
const ROLES = [
|
|
32
|
+
{ value: "r-admin", label: "Administrator", group: "Roles" },
|
|
33
|
+
{ value: "r-review", label: "Reviewer", group: "Roles" },
|
|
34
|
+
{ value: "r-observer", label: "Observer", group: "Roles" },
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
const ISSUES = Array.from({ length: 300 }, (_, i) => ({
|
|
38
|
+
value: `PKG-${i + 1}`,
|
|
39
|
+
label: `PKG-${i + 1}`,
|
|
40
|
+
sublabel: `Requirement ${i + 1} — imported from the spec sheet`,
|
|
41
|
+
}));
|
|
42
|
+
|
|
43
|
+
const delay = <T,>(value: T) => new Promise<T>((r) => setTimeout(() => r(value), 120));
|
|
44
|
+
|
|
45
|
+
export default function Demo() {
|
|
46
|
+
const [small, setSmall] = useState<string | null>("u2");
|
|
47
|
+
const [owner, setOwner] = useState<string | null>("");
|
|
48
|
+
const [approvers, setApprovers] = useState<string[]>(["r-review"]);
|
|
49
|
+
const [issue, setIssue] = useState<string | null>("PKG-1");
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<PageContainer
|
|
53
|
+
title="RecordPicker"
|
|
54
|
+
subtitle="One control whose shape follows the size of the set — dropdown under the threshold, searchable dialog over it"
|
|
55
|
+
>
|
|
56
|
+
<Flex direction="col" gap="lg">
|
|
57
|
+
<Card>
|
|
58
|
+
<CardHeader>
|
|
59
|
+
<CardTitle level={2}>Under the threshold, it IS a Select</CardTitle>
|
|
60
|
+
<CardDescription>
|
|
61
|
+
Three people, so nothing is gained by a dialog. The same component renders Select —
|
|
62
|
+
same trigger, same panel, same search. Nothing here is a lookalike.
|
|
63
|
+
</CardDescription>
|
|
64
|
+
</CardHeader>
|
|
65
|
+
<CardContent>
|
|
66
|
+
<Flex direction="col" gap="sm" align="start">
|
|
67
|
+
<RecordPicker options={SMALL} value={small} onValueChange={(v) => setSmall(v as string)} />
|
|
68
|
+
<Text as="p" size="2xs" tone="muted" tabular>
|
|
69
|
+
value: {JSON.stringify(small)}
|
|
70
|
+
</Text>
|
|
71
|
+
</Flex>
|
|
72
|
+
</CardContent>
|
|
73
|
+
</Card>
|
|
74
|
+
|
|
75
|
+
<Card>
|
|
76
|
+
<CardHeader>
|
|
77
|
+
<CardTitle level={2}>Assigning an owner out of 800</CardTitle>
|
|
78
|
+
<CardDescription>
|
|
79
|
+
The case the report is about: this field was a dropdown with no search. `count` comes
|
|
80
|
+
from the server — the page of rows in hand says nothing about the set behind it. The
|
|
81
|
+
pinned “Unassigned” row is a value the record HOLDS, not an empty field.
|
|
82
|
+
</CardDescription>
|
|
83
|
+
</CardHeader>
|
|
84
|
+
<CardContent>
|
|
85
|
+
<Flex direction="col" gap="sm" align="start">
|
|
86
|
+
<RecordPicker
|
|
87
|
+
count={PEOPLE.length}
|
|
88
|
+
loadOptions={async ({ query, filters }) =>
|
|
89
|
+
delay({
|
|
90
|
+
options: PEOPLE.filter(
|
|
91
|
+
(p) =>
|
|
92
|
+
p.label.toLowerCase().includes(query.toLowerCase()) &&
|
|
93
|
+
(!filters.scope || filters.scope === "project"),
|
|
94
|
+
).slice(0, 40),
|
|
95
|
+
})
|
|
96
|
+
}
|
|
97
|
+
filters={[
|
|
98
|
+
{
|
|
99
|
+
name: "scope",
|
|
100
|
+
label: "Scope",
|
|
101
|
+
options: [
|
|
102
|
+
{ value: "project", label: "On this project" },
|
|
103
|
+
{ value: "all", label: "Everyone" },
|
|
104
|
+
],
|
|
105
|
+
},
|
|
106
|
+
]}
|
|
107
|
+
emptyOption={{ value: "", label: "Unassigned" }}
|
|
108
|
+
selectedOptions={[{ value: "", label: "Unassigned" }]}
|
|
109
|
+
value={owner}
|
|
110
|
+
onValueChange={(v) => setOwner(v as string)}
|
|
111
|
+
dialogTitle="Choose an owner"
|
|
112
|
+
/>
|
|
113
|
+
<Text as="p" size="2xs" tone="muted" tabular>
|
|
114
|
+
value: {JSON.stringify(owner)}
|
|
115
|
+
</Text>
|
|
116
|
+
</Flex>
|
|
117
|
+
</CardContent>
|
|
118
|
+
</Card>
|
|
119
|
+
|
|
120
|
+
<Card>
|
|
121
|
+
<CardHeader>
|
|
122
|
+
<CardTitle level={2}>Two kinds of thing in one field</CardTitle>
|
|
123
|
+
<CardDescription>
|
|
124
|
+
An approval step accepts a PERSON or a ROLE. They are two `group`s in one list rather
|
|
125
|
+
than two controls, and the option `icon` is what keeps the chips apart once chosen.
|
|
126
|
+
`multiple` commits on Confirm, so a mis-click is undone by Cancel.
|
|
127
|
+
</CardDescription>
|
|
128
|
+
</CardHeader>
|
|
129
|
+
<CardContent>
|
|
130
|
+
<Flex direction="col" gap="sm" align="start">
|
|
131
|
+
<RecordPicker
|
|
132
|
+
mode="multiple"
|
|
133
|
+
count={PEOPLE.length + ROLES.length}
|
|
134
|
+
loadOptions={async ({ query }) =>
|
|
135
|
+
delay({
|
|
136
|
+
options: [
|
|
137
|
+
...ROLES.filter((r) => r.label.toLowerCase().includes(query.toLowerCase())).map(
|
|
138
|
+
(r) => ({ ...r, icon: <Icon as={Shield} size="sm" tone="muted" /> }),
|
|
139
|
+
),
|
|
140
|
+
...PEOPLE.filter((p) => p.label.toLowerCase().includes(query.toLowerCase()))
|
|
141
|
+
.slice(0, 30)
|
|
142
|
+
.map((p) => ({
|
|
143
|
+
...p,
|
|
144
|
+
group: "Users",
|
|
145
|
+
icon: <Icon as={User} size="sm" tone="muted" />,
|
|
146
|
+
})),
|
|
147
|
+
],
|
|
148
|
+
})
|
|
149
|
+
}
|
|
150
|
+
selectedOptions={ROLES}
|
|
151
|
+
value={approvers}
|
|
152
|
+
onValueChange={(v) => setApprovers(v as string[])}
|
|
153
|
+
dialogTitle="Choose approvers"
|
|
154
|
+
/>
|
|
155
|
+
<Text as="p" size="2xs" tone="muted" tabular>
|
|
156
|
+
value: {JSON.stringify(approvers)}
|
|
157
|
+
</Text>
|
|
158
|
+
</Flex>
|
|
159
|
+
</CardContent>
|
|
160
|
+
</Card>
|
|
161
|
+
|
|
162
|
+
<Card>
|
|
163
|
+
<CardHeader>
|
|
164
|
+
<CardTitle level={2}>A record, by key or by title</CardTitle>
|
|
165
|
+
<CardDescription>
|
|
166
|
+
This field used to be free text: you typed the key, and a wrong one failed with a 422
|
|
167
|
+
AFTER save. Searching both the key and the title, with the key shown beside it, means
|
|
168
|
+
the value cannot be wrong by the time it is submitted.
|
|
169
|
+
</CardDescription>
|
|
170
|
+
</CardHeader>
|
|
171
|
+
<CardContent>
|
|
172
|
+
<Flex direction="col" gap="sm" align="start">
|
|
173
|
+
<RecordPicker
|
|
174
|
+
count={ISSUES.length}
|
|
175
|
+
loadOptions={async ({ query, filters }) =>
|
|
176
|
+
delay({
|
|
177
|
+
options: ISSUES.filter(
|
|
178
|
+
(o) =>
|
|
179
|
+
(o.label + o.sublabel).toLowerCase().includes(query.toLowerCase()) &&
|
|
180
|
+
(!filters.state || filters.state === "open"),
|
|
181
|
+
).slice(0, 40),
|
|
182
|
+
})
|
|
183
|
+
}
|
|
184
|
+
filters={[
|
|
185
|
+
{
|
|
186
|
+
name: "state",
|
|
187
|
+
label: "State",
|
|
188
|
+
options: [
|
|
189
|
+
{ value: "open", label: "Open" },
|
|
190
|
+
{ value: "closed", label: "Closed" },
|
|
191
|
+
],
|
|
192
|
+
},
|
|
193
|
+
]}
|
|
194
|
+
selectedOptions={[{ value: "PKG-1", label: "PKG-1", sublabel: "Requirement 1" }]}
|
|
195
|
+
value={issue}
|
|
196
|
+
onValueChange={(v) => setIssue(v as string)}
|
|
197
|
+
dialogTitle="Choose a requirement"
|
|
198
|
+
/>
|
|
199
|
+
<Text as="p" size="2xs" tone="muted" tabular>
|
|
200
|
+
value: {JSON.stringify(issue)}
|
|
201
|
+
</Text>
|
|
202
|
+
</Flex>
|
|
203
|
+
</CardContent>
|
|
204
|
+
</Card>
|
|
205
|
+
</Flex>
|
|
206
|
+
</PageContainer>
|
|
207
|
+
);
|
|
208
|
+
}
|
|
@@ -425,6 +425,34 @@ export default function Demo() {
|
|
|
425
425
|
<VisuallyHidden>{t("textExamples.preservedText")}</VisuallyHidden>
|
|
426
426
|
</CardContent>
|
|
427
427
|
</Card>
|
|
428
|
+
<Card>
|
|
429
|
+
<CardHeader>
|
|
430
|
+
<CardTitle level={2}>{t("textExamples.breakTitle")}</CardTitle>
|
|
431
|
+
<CardDescription>{t("textExamples.breakDescription")}</CardDescription>
|
|
432
|
+
</CardHeader>
|
|
433
|
+
<CardContent flush>
|
|
434
|
+
<Table>
|
|
435
|
+
<TableHeader>
|
|
436
|
+
<TableRow>
|
|
437
|
+
<TableHead>{t("textExamples.breakColumnOwner")}</TableHead>
|
|
438
|
+
<TableHead>{t("textExamples.breakColumnEmail")}</TableHead>
|
|
439
|
+
</TableRow>
|
|
440
|
+
</TableHeader>
|
|
441
|
+
<TableBody>
|
|
442
|
+
<TableRow>
|
|
443
|
+
<TableCell>
|
|
444
|
+
<Text size="sm">{t("textExamples.breakSampleName")}</Text>
|
|
445
|
+
</TableCell>
|
|
446
|
+
<TableCell>
|
|
447
|
+
<Text size="sm" break="anywhere">
|
|
448
|
+
hanako.sato.customer-success-team@example-enterprise-holdings.co.jp
|
|
449
|
+
</Text>
|
|
450
|
+
</TableCell>
|
|
451
|
+
</TableRow>
|
|
452
|
+
</TableBody>
|
|
453
|
+
</Table>
|
|
454
|
+
</CardContent>
|
|
455
|
+
</Card>
|
|
428
456
|
</Flex>
|
|
429
457
|
</PageContainer>
|
|
430
458
|
);
|