@sarunyu/system-one 4.9.5 → 4.9.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/llms.txt CHANGED
@@ -330,15 +330,13 @@ Single-select dropdown.
330
330
  options={[
331
331
  { label: "Option A", value: "a" },
332
332
  { label: "Option B", value: "b" },
333
- { label: "Disabled", value: "c", disabled: true },
334
333
  ]}
335
334
  value={selected}
336
335
  onChange={setSelected}
337
336
  />
338
337
  ```
339
338
 
340
- Props: `placeholder`, `options: { label, value, disabled? }[]`, `value`, `onChange(value)`,
341
- `disabled`, `className`.
339
+ Props: `placeholder`, `label`, `required`, `forceState` (`"default"` | `"focus"` | `"error"` | `"disabled"`), `errorMessage`, `helperText`, `options: { label, value }[]`, `value`, `onChange(value)`, `className`. To disable, pass `forceState="disabled"` — there is no top-level `disabled` prop.
342
340
 
343
341
  ### DropdownMultiple
344
342
 
@@ -348,24 +346,24 @@ Multi-select dropdown with checkboxes.
348
346
  <DropdownMultiple
349
347
  placeholder="Select tags"
350
348
  options={tagOptions}
351
- values={selected}
349
+ value={selected}
352
350
  onChange={setSelected}
353
351
  />
354
352
  ```
355
353
 
356
- Props: `placeholder`, `options`, `values: string[]`, `onChange(values)`, `disabled`, `className`.
354
+ Props: `placeholder`, `label`, `required`, `forceState`, `errorMessage`, `helperText`, `options`, `value: string[]`, `onChange(value: string[])`, `className`. The controlled prop is `value` (not `values`). To disable, use `forceState="disabled"`.
357
355
 
358
356
  ---
359
357
 
360
358
  ### Checkbox
361
359
 
362
360
  ```tsx
363
- <Checkbox checked={agreed} onCheckedChange={setAgreed} label="I agree to the terms" />
364
- <Checkbox checked="indeterminate" onCheckedChange={setAll} label="Select all" />
365
- <Checkbox checked={sub} onCheckedChange={setSub} label="Subscribe" disabled />
361
+ <Checkbox checked={agreed} onChange={setAgreed} label="I agree to the terms" />
362
+ <Checkbox checked="indeterminate" onChange={setAll} label="Select all" />
363
+ <Checkbox checked={sub} onChange={setSub} label="Subscribe" disabled />
366
364
  ```
367
365
 
368
- `checked` is `boolean | "indeterminate"`. Always provide `label` — don't wrap Checkbox in a `<label>`.
366
+ `checked` is `boolean | "indeterminate"`. `onChange` receives a boolean (`(next: boolean) => void`) — NOT an event, NOT `onCheckedChange`. Always provide `label` — don't wrap Checkbox in a `<label>`.
369
367
 
370
368
  ### Toggle
371
369
 
@@ -395,11 +393,13 @@ Render a group — use `name` to bind siblings.
395
393
 
396
394
  ```tsx
397
395
  <div className="flex flex-col gap-2">
398
- <Radio name="plan" value="free" checked={plan === "free"} onChange={setPlan} label="Free" />
399
- <Radio name="plan" value="pro" checked={plan === "pro"} onChange={setPlan} label="Pro" />
396
+ <Radio name="plan" value="free" checked={plan === "free"} onChange={() => setPlan("free")} label="Free" />
397
+ <Radio name="plan" value="pro" checked={plan === "pro"} onChange={() => setPlan("pro")} label="Pro" />
400
398
  </div>
401
399
  ```
402
400
 
401
+ `onChange` receives a boolean (`(next: boolean) => void`) — fires with `true` when the radio becomes selected. To track which value was picked, ignore the arg and set the value directly: `onChange={() => setPlan("pro")}`.
402
+
403
403
  ---
404
404
 
405
405
  ### Tag
@@ -412,11 +412,13 @@ type TagVariant = "blue" | "green" | "yellow" | "red" | "gray" | "lime";
412
412
 
413
413
  <Tag text="Active" variant="green" />
414
414
  <Tag text="Draft" variant="yellow" />
415
- <Tag text="Filter: Design" close onClose={remove} />
415
+ <Tag text="Filter: Design" close />
416
416
  <Tag text="Small" variant="blue" size="small" />
417
417
  ```
418
418
 
419
- Props: `text`, `variant`, `size` (`"large"` default | `"small"`), `close`, `onClose`, `className`.
419
+ Props: `text`, `variant`, `size` (`"large"` default | `"small"`), `state` (`"default"` | `"hover"` | `"disabled"`), `icon` (boolean — leading dot), `close` (boolean — visual × button only), `className`.
420
+
421
+ **Note** — `close` is purely visual; the Tag does not handle dismiss. To make a removable tag, wrap it in a clickable parent (`<button onClick={remove}><Tag close text="…" /></button>`) or use `<DropdownMultiple>`'s built-in removable chips.
420
422
 
421
423
  ### StatusTag
422
424
 
@@ -674,15 +676,33 @@ Props:
674
676
 
675
677
  ### DateInput / TimeInput
676
678
 
679
+ Modes: `"single"` (default) | `"range"`. There is **no `"multiple"` mode**.
680
+
681
+ Each mode uses different value props — single mode uses `value` + `onChange`, range mode uses `dateRange` + `onRangeChange` (or `startTime`/`endTime` + `onStartChange`/`onEndChange` for TimeInput).
682
+
677
683
  ```tsx
684
+ // DateInput — single
678
685
  <DateInput placeholder="Select date" mode="single" value={date} onChange={setDate} />
679
- <DateInput mode="range" value={range} onChange={setRange} />
680
- <DateInput mode="multiple" value={dates} onChange={setDates} />
681
686
 
687
+ // DateInput — range (different prop names!)
688
+ <DateInput mode="range" dateRange={range} onRangeChange={setRange} />
689
+
690
+ // TimeInput — single
682
691
  <TimeInput placeholder="Start time" value={time} onChange={setTime} />
683
- <TimeInput mode="range" value={timeRange} onChange={setTimeRange} />
692
+
693
+ // TimeInput — range (different prop names!)
694
+ <TimeInput
695
+ mode="range"
696
+ startTime={start}
697
+ endTime={end}
698
+ onStartChange={setStart}
699
+ onEndChange={setEnd}
700
+ />
684
701
  ```
685
702
 
703
+ DateInput types: `value: Date | undefined`, `dateRange: DateRange` (re-exported from react-day-picker — `{ from?: Date; to?: Date }`).
704
+ TimeInput types: `value: TimeValue` where `TimeValue = { hour: 0–23, minute: 0–59 }`.
705
+
686
706
  Always format `"DD MMM YYYY"` for display (system format). Don't mix Thai month names with C.E. year.
687
707
 
688
708
  ### OptionList
@@ -987,7 +1007,7 @@ export function LoginSheet({
987
1007
  <div className="flex flex-col gap-4">
988
1008
  <Input placeholder="Email" value={email} onChange={setEmail} required />
989
1009
  <Input placeholder="Password" value={pw} onChange={setPw} type="password" required />
990
- <Checkbox checked={remember} onCheckedChange={setRmb} label="Remember me" />
1010
+ <Checkbox checked={remember} onChange={setRmb} label="Remember me" />
991
1011
  <Button variant="primary" size="xl" className="w-full" onClick={() => onOpenChange(false)}>
992
1012
  Sign in
993
1013
  </Button>
@@ -1109,7 +1129,7 @@ export function LoginPage() {
1109
1129
  <div className="flex flex-col gap-4">
1110
1130
  <Input placeholder="Email" type="email" value={email} onChange={setEmail} required />
1111
1131
  <Input placeholder="Password" type="password" value={pw} onChange={setPw} required />
1112
- <Checkbox checked={remember} onCheckedChange={setRmb} label="Remember me" />
1132
+ <Checkbox checked={remember} onChange={setRmb} label="Remember me" />
1113
1133
  </div>
1114
1134
  <Button variant="primary" size="lg" className="w-full">Sign in</Button>
1115
1135
  <p className="text-center text-sm text-muted-foreground">
@@ -1199,7 +1219,7 @@ export function SettingsPage() {
1199
1219
  <DropdownMultiple
1200
1220
  placeholder="Interests"
1201
1221
  options={interests}
1202
- values={picked}
1222
+ value={picked}
1203
1223
  onChange={setPicked}
1204
1224
  />
1205
1225
  <DateInput placeholder="Birthday" mode="single" value={dob} onChange={setDob} />
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sarunyu/system-one",
3
- "version": "4.9.5",
3
+ "version": "4.9.7",
4
4
  "type": "module",
5
5
  "description": "A production-ready React design system built for AI-powered web generation tools (Figma Make, Lovable, V0). Tailwind CSS v4 + CSS custom properties for full theming support.",
6
6
  "keywords": [