@box-kite/react 2.2.6 → 2.2.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/.claude/rules/box-kite-rules.md +2 -0
- package/.claude/skills/box-kite/SKILL.md +2 -0
- package/.claude/skills/box-kite/references/extending.md +10 -0
- package/.claude/skills/box-kite/references/styling.md +3 -2
- package/.cursor/rules/box-kite.mdc +2 -0
- package/AGENTS.md +2 -0
- package/BOX_AI_CONTEXT.md +52 -2
- package/BOX_KITE_AI_CONTEXT.md +52 -2
- package/box.cjs +1 -1
- package/box.d.ts +5 -0
- package/box.mjs +1 -1
- package/client.cjs +1 -1
- package/client.mjs +88 -57
- package/components/dataGrid/models/headerCellModel.d.ts +1 -0
- package/components/dataGrid.cjs +1 -1
- package/components/dataGrid.mjs +28 -27
- package/components/semantics.d.ts +29 -29
- package/create/src/index.d.ts +1 -0
- package/create/src/options.d.ts +27 -0
- package/create/src/options.test.d.ts +1 -0
- package/create/src/packageManager.d.ts +5 -0
- package/create/src/project.d.ts +25 -0
- package/create/src/project.test.d.ts +1 -0
- package/create/templates/ts/designs/azure.d.ts +5 -0
- package/create/templates/ts/designs/ember.d.ts +5 -0
- package/create/templates/ts/designs/mono.d.ts +5 -0
- package/create/templates/ts/src/App.d.ts +2 -0
- package/create/templates/ts/src/design.d.ts +5 -0
- package/create/templates/ts/src/main.d.ts +0 -0
- package/dataGridList.cjs +1 -1
- package/dataGridList.mjs +7 -7
- package/docs/props.md +19 -19
- package/package.json +36 -31
- package/react/theme/theme.d.ts +9 -0
- package/react/theme/themeContext.d.ts +2 -0
- package/rsc.cjs +1 -1
- package/rsc.d.ts +3 -0
- package/rsc.mjs +1 -1
|
@@ -95,3 +95,5 @@ globs: '**/*.{ts,tsx,jsx}'
|
|
|
95
95
|
53. **A date, a time or a moment is an ISO string, and its shape is its kind.** `2026-10-19` is a date (no time, no zone — the same day everywhere), `14:30:00` a time, `2026-10-19T14:30:00` a wall clock with no zone, and anything with an offset (`…+03:00`, `…Z`) an instant. **Never hold a `Date`**: it is a moment in the runtime's zone, which is how a birthday becomes the day before in another country. `@box-kite/react/date` (no React, no engine, under 8 KB gz, every locale and zone from `Intl`) converts by naming the target — `toUtc(value, { from: 'Europe/Chisinau' })`, `toLocal(value)`, `toZone(value, 'America/New_York')`, `toPlainDate(value, { zone })` — and `format(value, { locale, zone, dateStyle })` writes one in the reader's words (presets, never format tokens); `parse(text, { locale, kind })` reads ISO, a `Date`, epoch ms, an HTTP date or text in the locale's order (`03/04/2026` is March in `en-US` and April in `en-GB`). `add`/`subtract` move the wall clock for days and up and the instant for hours and down, so a day later is the same time tomorrow across DST; `startOf(…, 'week')` follows the locale. **`'local'` is the reader**: the browser's zone in a browser, and on a server `configureDates({ timeZone })` or a `<DateProvider timeZone>` — read off the cookie `zoneCookie()` writes, with `readZoneCookie(header)` — while `systemZone()` is always the server's own. **The controls** — `<DateField>` (`components/dateField`: `type="date"|"time"|"datetime"`, segments in the locale's order, nothing typed is ever parsed), `<Calendar>` (`components/calendar`, `mode="range"`), `<DatePicker>`/`<DateRangePicker>` (`components/datePicker`, the top layer, a list of times every `step` minutes for `time`/`datetime`, `presets`), `<TimeZoneSelect>` (`components/timeZoneSelect`, the IANA name as its value) and `<DateTime value>` (`components/dateTime`, a `<time datetime>` in the reader's zone) — take and give that string, and **`onValueChange(value, { reason, utc, local, zoned, date, epoch, offset })`** hands the readings over beside it. A date-time's `zone` is `'local'` (default), `'utc'`, an IANA name or `'none'` (a wall clock that belongs to nobody); the value is the instant on that zone's clock (`…Z` for UTC). **They cannot cause a hydration error**: a server and a hydrating browser both render in the fallback (`UTC`, `en-US`, or what a `DateProvider` says) and the render after switches to the reader. `name` posts the canonical string and `required` stops the form; a DataGrid column takes `editor: 'date'|'time'|'datetime'`, `dateFormat` and `filterable: { type: 'date' }`, from a chunk fetched only when a grid shows a date. `<Textbox type="date">` is still the native input, whose language is the browser's rather than the page's.
|
|
96
96
|
|
|
97
97
|
Full reference: `src/BOX_KITE_AI_CONTEXT.md` or invoke `/box-kite` skill.
|
|
98
|
+
|
|
99
|
+
54. **A design is two families and a `Box.components()` object, and it is chosen in CSS.** Every built-in component is drawn in `accent` and `base` — two palette families that start as copies of `indigo` and `gray` — so `vars={Box.palette({ accent: 'orange', base: 'stone' })}` on an ancestor recolours every component inside it, by family name or with a ramp of your own (`{ 500: 'oklch(…)' }`); write `accent-*`/`base-*` in your own components when they should follow, and a named family when the colour is the content. The rest of a design is `Box.components(styles, { design: 'ember' })`: merged over the app's own and applied under `data-design="ember"`, which `<Box.Theme design="classic" designStorageKey="design">` writes on `<html>` and `Box.useDesign()` switches — chosen by an attribute rather than by context, so a pre-paint script that copies the stored name onto `<html>` is all a prerendered page needs, and server and browser render the same classes. **Three things to know.** A design merges and cannot delete a key, so it takes something back off with that prop's `none` (`shadow: 'none'`, `bgGradient: 'none'` — never `bgImage: 'none'`, which loses `background-image` to `bgGradient`). A design nested inside another stops the outer one, but `vars` inherit, so a `data-design="classic"` preview inside an Ember page redeclares its own `Box.palette()`. And a Box under `<Box.Components value>` resolves against that registry and no named design — `Box.createComponents()` is still the answer for a subtree whose design React decides. A part extends like a component does (`trigger: { extends: 'button' }`, `'dialog.title'`), and `letterSpacing` takes the tracking names `tighter`…`widest` in `em`.
|
|
@@ -168,3 +168,5 @@ Detect the package manager from the lock file rather than asking:
|
|
|
168
168
|
53. **A date, a time or a moment is an ISO string, and its shape is its kind.** `2026-10-19` is a date (no time, no zone — the same day everywhere), `14:30:00` a time, `2026-10-19T14:30:00` a wall clock with no zone, and anything with an offset (`…+03:00`, `…Z`) an instant. **Never hold a `Date`**: it is a moment in the runtime's zone, which is how a birthday becomes the day before in another country. `@box-kite/react/date` (no React, no engine, under 8 KB gz, every locale and zone from `Intl`) converts by naming the target — `toUtc(value, { from: 'Europe/Chisinau' })`, `toLocal(value)`, `toZone(value, 'America/New_York')`, `toPlainDate(value, { zone })` — and `format(value, { locale, zone, dateStyle })` writes one in the reader's words (presets, never format tokens); `parse(text, { locale, kind })` reads ISO, a `Date`, epoch ms, an HTTP date or text in the locale's order (`03/04/2026` is March in `en-US` and April in `en-GB`). `add`/`subtract` move the wall clock for days and up and the instant for hours and down, so a day later is the same time tomorrow across DST; `startOf(…, 'week')` follows the locale. **`'local'` is the reader**: the browser's zone in a browser, and on a server `configureDates({ timeZone })` or a `<DateProvider timeZone>` — read off the cookie `zoneCookie()` writes, with `readZoneCookie(header)` — while `systemZone()` is always the server's own. **The controls** — `<DateField>` (`components/dateField`: `type="date"|"time"|"datetime"`, segments in the locale's order, nothing typed is ever parsed), `<Calendar>` (`components/calendar`, `mode="range"`), `<DatePicker>`/`<DateRangePicker>` (`components/datePicker`, the top layer, a list of times every `step` minutes for `time`/`datetime`, `presets`), `<TimeZoneSelect>` (`components/timeZoneSelect`, the IANA name as its value) and `<DateTime value>` (`components/dateTime`, a `<time datetime>` in the reader's zone) — take and give that string, and **`onValueChange(value, { reason, utc, local, zoned, date, epoch, offset })`** hands the readings over beside it. A date-time's `zone` is `'local'` (default), `'utc'`, an IANA name or `'none'` (a wall clock that belongs to nobody); the value is the instant on that zone's clock (`…Z` for UTC). **They cannot cause a hydration error**: a server and a hydrating browser both render in the fallback (`UTC`, `en-US`, or what a `DateProvider` says) and the render after switches to the reader. `name` posts the canonical string and `required` stops the form; a DataGrid column takes `editor: 'date'|'time'|'datetime'`, `dateFormat` and `filterable: { type: 'date' }`, from a chunk fetched only when a grid shows a date. `<Textbox type="date">` is still the native input, whose language is the browser's rather than the page's.
|
|
169
169
|
|
|
170
170
|
Full reference: `references/` beside this file, and `docs/props.md` inside the package.
|
|
171
|
+
|
|
172
|
+
54. **A design is two families and a `Box.components()` object, and it is chosen in CSS.** Every built-in component is drawn in `accent` and `base` — two palette families that start as copies of `indigo` and `gray` — so `vars={Box.palette({ accent: 'orange', base: 'stone' })}` on an ancestor recolours every component inside it, by family name or with a ramp of your own (`{ 500: 'oklch(…)' }`); write `accent-*`/`base-*` in your own components when they should follow, and a named family when the colour is the content. The rest of a design is `Box.components(styles, { design: 'ember' })`: merged over the app's own and applied under `data-design="ember"`, which `<Box.Theme design="classic" designStorageKey="design">` writes on `<html>` and `Box.useDesign()` switches — chosen by an attribute rather than by context, so a pre-paint script that copies the stored name onto `<html>` is all a prerendered page needs, and server and browser render the same classes. **Three things to know.** A design merges and cannot delete a key, so it takes something back off with that prop's `none` (`shadow: 'none'`, `bgGradient: 'none'` — never `bgImage: 'none'`, which loses `background-image` to `bgGradient`). A design nested inside another stops the outer one, but `vars` inherit, so a `data-design="classic"` preview inside an Ember page redeclares its own `Box.palette()`. And a Box under `<Box.Components value>` resolves against that registry and no named design — `Box.createComponents()` is still the answer for a subtree whose design React decides. A part extends like a component does (`trigger: { extends: 'button' }`, `'dialog.title'`), and `letterSpacing` takes the tracking names `tighter`…`widest` in `em`.
|
|
@@ -16,9 +16,19 @@ export const components = Box.components({
|
|
|
16
16
|
children: { header: { styles: { fontSize: 18, fontWeight: 600 } } },
|
|
17
17
|
},
|
|
18
18
|
subgrid: { extends: 'datagrid', styles: { b: 0, shadow: 'none' } },
|
|
19
|
+
// A part extends too: a component by name, or another part by its dotted path.
|
|
20
|
+
picker: { children: { trigger: { extends: 'button', styles: { px: 3 } } } },
|
|
19
21
|
});
|
|
20
22
|
```
|
|
21
23
|
|
|
24
|
+
**A second design, chosen in CSS**: `Box.components(styles, { design: 'ember' })` merges `styles` over the app's components
|
|
25
|
+
and applies them under `data-design="ember"` — `<Box.Theme design="classic" designStorageKey="design">` writes the
|
|
26
|
+
attribute, `Box.useDesign()` switches it, and a pre-paint script that copies the stored value onto `<html>` means no flash
|
|
27
|
+
on a prerendered page. Each design rule is one class more specific than the app's, so every state is outranked; a design
|
|
28
|
+
cannot delete a key, so it writes `none` (`shadow: 'none'`, `bgGradient: 'none'`). Its colours are `Box.palette()` in a
|
|
29
|
+
root `dataAttr={{ 'design=ember': { vars: … } }}`, since every built-in component is drawn in `accent` and `base`. A
|
|
30
|
+
subtree whose design React decides is still `Box.createComponents()` + `<Box.Components value>`.
|
|
31
|
+
|
|
22
32
|
## Extension System
|
|
23
33
|
|
|
24
34
|
```tsx
|
|
@@ -7,7 +7,7 @@ Every prop by category, the six kinds of nesting, and the theme system. Read thi
|
|
|
7
7
|
**Spacing**: `p`/`px`/`py`/`pt`/`pr`/`pb`/`pl`/`ps`/`pe`, `m`/`mx`/`my`/`mt`/`mr`/`mb`/`ml`/`ms`/`me`, `gap` — the axis pair is already logical (`px` is `padding-inline`) and `ps`/`pe`, `ms`/`me` are its two sides
|
|
8
8
|
**Layout**: `display`, `d` (flex-direction), `wrap`, `ai` (align-items), `jc` (justify-content), `justifyItems`/`placeItems`/`placeContent`/`alignContent`/`alignSelf`/`justifySelf`, `flex`/`grow`/`shrink`, `container`/`containerName`/`containerType` (a query container — see `cq`). Every alignment prop also takes the **overflow-safe** forms — `'safe center'`, `'safe start'`, `'safe end'` and the `'unsafe …'` twins: `safe center` centres until the content stops fitting and then aligns to `start`, where plain `center` overflows both edges and the half above the scrollable origin cannot be reached at all. `aspectRatio` is `'square'` (1/1), `'video'` (16/9), a compact ratio (`'4/3'`), a number, or `'auto'`
|
|
9
9
|
**Sizing**: `width`/`height` — number (÷4=rem), `'auto'`, `'fit'` (100%), `'fit-screen'` (100vw/vh), fractions (`'1/2'`…), `'33%'`. `minWidth`/`maxWidth`/`minHeight`/`maxHeight` same. All accept `"5%"`.
|
|
10
|
-
**Colors**: `bgColor`/`color`/`borderColor`/`outlineColor`/`fill`/`stroke` — Tailwind's OKLCH palette, 26 families × 11 steps `'50'`..`'950'` (slate/gray/zinc/neutral/stone/mauve/mist/olive/taupe/red/orange/amber/yellow/lime/green/emerald/teal/cyan/sky/blue/indigo/violet/purple/fuchsia/pink/rose), plus `'white'`/`'black'`/`'transparent'`/`'currentColor'`. **Opacity modifier on any colour value**: `bgColor="blue-500/40"` → `color-mix(in oklab, var(--blue-500) 40%, transparent)` — the mix wraps the _variable_, so it stays themed and shared; unlike `opacity` it fades one declaration, not the element. Works in `vars` and on a `Box.extend()` variable (`"brand/30"`); an unknown token or a percentage outside 0–100 emits nothing
|
|
10
|
+
**Colors**: `bgColor`/`color`/`borderColor`/`outlineColor`/`fill`/`stroke` — Tailwind's OKLCH palette, 26 families × 11 steps `'50'`..`'950'` (slate/gray/zinc/neutral/stone/mauve/mist/olive/taupe/red/orange/amber/yellow/lime/green/emerald/teal/cyan/sky/blue/indigo/violet/purple/fuchsia/pink/rose), plus `'white'`/`'black'`/`'transparent'`/`'currentColor'`. **Opacity modifier on any colour value**: `bgColor="blue-500/40"` → `color-mix(in oklab, var(--blue-500) 40%, transparent)` — the mix wraps the _variable_, so it stays themed and shared; unlike `opacity` it fades one declaration, not the element. Works in `vars` and on a `Box.extend()` variable (`"brand/30"`); an unknown token or a percentage outside 0–100 emits nothing. Two more families, `accent` and `base` (copies of `indigo` and `gray`), are what every built-in component is drawn in; `vars={Box.palette({ accent: 'orange', base: 'stone' })}` repoints them for a subtree, by family name or with a ramp of your own
|
|
11
11
|
**Borders**: `b`/`bx`/`by`/`bt`/`br`/`bb`/`bl`/`bs`/`be` (px — `bs`/`be` are the logical sides), `borderRadius` (÷4) and its nine physical corners plus six logical ones (`borderRadiusStart`/`borderRadiusEnd`, and `borderRadiusStartStart`/`StartEnd`/`EndEnd`/`EndStart` — **block axis first, inline axis second**), `borderStyle`
|
|
12
12
|
**Text**: `fontSize` (÷16), `fontWeight`, `lineHeight` (px), `textAlign` (`'start'`/`'end'` follow the text direction where `'left'`/`'right'` do not)/`textDecoration`/`textTransform`/`whiteSpace`/`textOverflow`, `textWrap`
|
|
13
13
|
**Position**: `position`, `top`/`right`/`bottom`/`left`/`inset`/`insetX`/`insetY`/`insetStart`/`insetEnd`, `zIndex` — number (÷4), `'auto'`, fractions (`'1/2'`, `'-1/3'`) or a percentage; `insetX`/`insetY` are `inset-inline`/`inset-block`, the way `mx`/`my` are `margin-inline`/`margin-block`, and `insetStart`/`insetEnd` are that axis's two sides
|
|
@@ -121,7 +121,8 @@ minimum**. `interpolate` names the space: `'srgb'`, `'hsl'`, `'oklab'`, `'oklch'
|
|
|
121
121
|
`'oklch'` is what keeps two stops out of the grey middle sRGB drags them through, and a `-longer` hue turns two stops
|
|
122
122
|
into a spectrum. The record is judged **whole**: one unknown stop, one misspelt key (`interpolat`), two kinds at once,
|
|
123
123
|
and the value emits no rule and no class name. It writes `background-image`, so `bgGradient` and `bgImage` are the
|
|
124
|
-
same property — use one.
|
|
124
|
+
same property — use one; `bgGradient: 'none'` is how a variant or a design takes a gradient off. `letterSpacing` is px as a
|
|
125
|
+
number and Tailwind's tracking names in `em` as a string (`'tighter'`…`'widest'`).
|
|
125
126
|
|
|
126
127
|
**Shadows stack, four at a time**: `box-shadow` is one property, so each layer sets its own custom property and all
|
|
127
128
|
four write the same composed declaration — a ring and an elevation coexist instead of the last rule winning.
|
|
@@ -103,3 +103,5 @@ This library is not in your training data: it was renamed at 1.0.0 (September 20
|
|
|
103
103
|
53. **A date, a time or a moment is an ISO string, and its shape is its kind.** `2026-10-19` is a date (no time, no zone — the same day everywhere), `14:30:00` a time, `2026-10-19T14:30:00` a wall clock with no zone, and anything with an offset (`…+03:00`, `…Z`) an instant. **Never hold a `Date`**: it is a moment in the runtime's zone, which is how a birthday becomes the day before in another country. `@box-kite/react/date` (no React, no engine, under 8 KB gz, every locale and zone from `Intl`) converts by naming the target — `toUtc(value, { from: 'Europe/Chisinau' })`, `toLocal(value)`, `toZone(value, 'America/New_York')`, `toPlainDate(value, { zone })` — and `format(value, { locale, zone, dateStyle })` writes one in the reader's words (presets, never format tokens); `parse(text, { locale, kind })` reads ISO, a `Date`, epoch ms, an HTTP date or text in the locale's order (`03/04/2026` is March in `en-US` and April in `en-GB`). `add`/`subtract` move the wall clock for days and up and the instant for hours and down, so a day later is the same time tomorrow across DST; `startOf(…, 'week')` follows the locale. **`'local'` is the reader**: the browser's zone in a browser, and on a server `configureDates({ timeZone })` or a `<DateProvider timeZone>` — read off the cookie `zoneCookie()` writes, with `readZoneCookie(header)` — while `systemZone()` is always the server's own. **The controls** — `<DateField>` (`components/dateField`: `type="date"|"time"|"datetime"`, segments in the locale's order, nothing typed is ever parsed), `<Calendar>` (`components/calendar`, `mode="range"`), `<DatePicker>`/`<DateRangePicker>` (`components/datePicker`, the top layer, a list of times every `step` minutes for `time`/`datetime`, `presets`), `<TimeZoneSelect>` (`components/timeZoneSelect`, the IANA name as its value) and `<DateTime value>` (`components/dateTime`, a `<time datetime>` in the reader's zone) — take and give that string, and **`onValueChange(value, { reason, utc, local, zoned, date, epoch, offset })`** hands the readings over beside it. A date-time's `zone` is `'local'` (default), `'utc'`, an IANA name or `'none'` (a wall clock that belongs to nobody); the value is the instant on that zone's clock (`…Z` for UTC). **They cannot cause a hydration error**: a server and a hydrating browser both render in the fallback (`UTC`, `en-US`, or what a `DateProvider` says) and the render after switches to the reader. `name` posts the canonical string and `required` stops the form; a DataGrid column takes `editor: 'date'|'time'|'datetime'`, `dateFormat` and `filterable: { type: 'date' }`, from a chunk fetched only when a grid shows a date. `<Textbox type="date">` is still the native input, whose language is the browser's rather than the page's.
|
|
104
104
|
|
|
105
105
|
Full reference: `node_modules/@box-kite/react/docs/props.md` in the project, or https://www.box-kite.dev/props.md — every prop, the CSS it writes and one measured example.
|
|
106
|
+
|
|
107
|
+
54. **A design is two families and a `Box.components()` object, and it is chosen in CSS.** Every built-in component is drawn in `accent` and `base` — two palette families that start as copies of `indigo` and `gray` — so `vars={Box.palette({ accent: 'orange', base: 'stone' })}` on an ancestor recolours every component inside it, by family name or with a ramp of your own (`{ 500: 'oklch(…)' }`); write `accent-*`/`base-*` in your own components when they should follow, and a named family when the colour is the content. The rest of a design is `Box.components(styles, { design: 'ember' })`: merged over the app's own and applied under `data-design="ember"`, which `<Box.Theme design="classic" designStorageKey="design">` writes on `<html>` and `Box.useDesign()` switches — chosen by an attribute rather than by context, so a pre-paint script that copies the stored name onto `<html>` is all a prerendered page needs, and server and browser render the same classes. **Three things to know.** A design merges and cannot delete a key, so it takes something back off with that prop's `none` (`shadow: 'none'`, `bgGradient: 'none'` — never `bgImage: 'none'`, which loses `background-image` to `bgGradient`). A design nested inside another stops the outer one, but `vars` inherit, so a `data-design="classic"` preview inside an Ember page redeclares its own `Box.palette()`. And a Box under `<Box.Components value>` resolves against that registry and no named design — `Box.createComponents()` is still the answer for a subtree whose design React decides. A part extends like a component does (`trigger: { extends: 'button' }`, `'dialog.title'`), and `letterSpacing` takes the tracking names `tighter`…`widest` in `em`.
|
package/AGENTS.md
CHANGED
|
@@ -135,3 +135,5 @@ Every value there is a prop, and every prop value becomes one class the engine i
|
|
|
135
135
|
53. **A date, a time or a moment is an ISO string, and its shape is its kind.** `2026-10-19` is a date (no time, no zone — the same day everywhere), `14:30:00` a time, `2026-10-19T14:30:00` a wall clock with no zone, and anything with an offset (`…+03:00`, `…Z`) an instant. **Never hold a `Date`**: it is a moment in the runtime's zone, which is how a birthday becomes the day before in another country. `@box-kite/react/date` (no React, no engine, under 8 KB gz, every locale and zone from `Intl`) converts by naming the target — `toUtc(value, { from: 'Europe/Chisinau' })`, `toLocal(value)`, `toZone(value, 'America/New_York')`, `toPlainDate(value, { zone })` — and `format(value, { locale, zone, dateStyle })` writes one in the reader's words (presets, never format tokens); `parse(text, { locale, kind })` reads ISO, a `Date`, epoch ms, an HTTP date or text in the locale's order (`03/04/2026` is March in `en-US` and April in `en-GB`). `add`/`subtract` move the wall clock for days and up and the instant for hours and down, so a day later is the same time tomorrow across DST; `startOf(…, 'week')` follows the locale. **`'local'` is the reader**: the browser's zone in a browser, and on a server `configureDates({ timeZone })` or a `<DateProvider timeZone>` — read off the cookie `zoneCookie()` writes, with `readZoneCookie(header)` — while `systemZone()` is always the server's own. **The controls** — `<DateField>` (`components/dateField`: `type="date"|"time"|"datetime"`, segments in the locale's order, nothing typed is ever parsed), `<Calendar>` (`components/calendar`, `mode="range"`), `<DatePicker>`/`<DateRangePicker>` (`components/datePicker`, the top layer, a list of times every `step` minutes for `time`/`datetime`, `presets`), `<TimeZoneSelect>` (`components/timeZoneSelect`, the IANA name as its value) and `<DateTime value>` (`components/dateTime`, a `<time datetime>` in the reader's zone) — take and give that string, and **`onValueChange(value, { reason, utc, local, zoned, date, epoch, offset })`** hands the readings over beside it. A date-time's `zone` is `'local'` (default), `'utc'`, an IANA name or `'none'` (a wall clock that belongs to nobody); the value is the instant on that zone's clock (`…Z` for UTC). **They cannot cause a hydration error**: a server and a hydrating browser both render in the fallback (`UTC`, `en-US`, or what a `DateProvider` says) and the render after switches to the reader. `name` posts the canonical string and `required` stops the form; a DataGrid column takes `editor: 'date'|'time'|'datetime'`, `dateFormat` and `filterable: { type: 'date' }`, from a chunk fetched only when a grid shows a date. `<Textbox type="date">` is still the native input, whose language is the browser's rather than the page's.
|
|
136
136
|
|
|
137
137
|
Full reference: `docs/props.md` and `BOX_KITE_AI_CONTEXT.md`, in this package.
|
|
138
|
+
|
|
139
|
+
54. **A design is two families and a `Box.components()` object, and it is chosen in CSS.** Every built-in component is drawn in `accent` and `base` — two palette families that start as copies of `indigo` and `gray` — so `vars={Box.palette({ accent: 'orange', base: 'stone' })}` on an ancestor recolours every component inside it, by family name or with a ramp of your own (`{ 500: 'oklch(…)' }`); write `accent-*`/`base-*` in your own components when they should follow, and a named family when the colour is the content. The rest of a design is `Box.components(styles, { design: 'ember' })`: merged over the app's own and applied under `data-design="ember"`, which `<Box.Theme design="classic" designStorageKey="design">` writes on `<html>` and `Box.useDesign()` switches — chosen by an attribute rather than by context, so a pre-paint script that copies the stored name onto `<html>` is all a prerendered page needs, and server and browser render the same classes. **Three things to know.** A design merges and cannot delete a key, so it takes something back off with that prop's `none` (`shadow: 'none'`, `bgGradient: 'none'` — never `bgImage: 'none'`, which loses `background-image` to `bgGradient`). A design nested inside another stops the outer one, but `vars` inherit, so a `data-design="classic"` preview inside an Ember page redeclares its own `Box.palette()`. And a Box under `<Box.Components value>` resolves against that registry and no named design — `Box.createComponents()` is still the answer for a subtree whose design React decides. A part extends like a component does (`trigger: { extends: 'button' }`, `'dialog.title'`), and `letterSpacing` takes the tracking names `tighter`…`widest` in `em`.
|
package/BOX_AI_CONTEXT.md
CHANGED
|
@@ -307,6 +307,19 @@ Any colour value takes a slash and a percentage:
|
|
|
307
307
|
- A token the palette does not have, or a percentage outside 0–100, produces **no rule and no class
|
|
308
308
|
name** — the same silence every unmatched value gets.
|
|
309
309
|
|
|
310
|
+
**Two more families, `accent` and `base`, are what every built-in component is drawn in.** They start as
|
|
311
|
+
copies of `indigo` and `gray`, so nothing changes until one is pointed somewhere. `Box.palette()` returns the
|
|
312
|
+
`vars` record that does it, for an element and its subtree — a family by name, or a ramp of your own:
|
|
313
|
+
|
|
314
|
+
```tsx
|
|
315
|
+
<Box vars={Box.palette({ accent: 'orange', base: 'stone' })} /> // every Button inside is orange
|
|
316
|
+
<Box vars={Box.palette({ accent: { 500: 'oklch(68% .19 42)' } })} /> // a step left out keeps its default
|
|
317
|
+
<Box theme={{ dark: { vars: Box.palette({ accent: 'amber' }) } }} /> // nests like any vars
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
Write `accent-*`/`base-*` in your own components when they should follow a design, and a named family when the
|
|
321
|
+
colour is the content (a status, a chart series). A class built from them reads `bgColor-accent-500`.
|
|
322
|
+
|
|
310
323
|
### Gradients, shadows and rings
|
|
311
324
|
|
|
312
325
|
A gradient is a **value**, written as a record — so its stops are palette tokens, it takes the opacity
|
|
@@ -330,7 +343,10 @@ modifier, it is themed, and two elements asking for the same one share a class.
|
|
|
330
343
|
- A stop is any colour value — a token, `blue-500/40`, a system colour, `var(--chart-1)` — or a
|
|
331
344
|
`[colour, position]` pair. **Two stops minimum**, and the record is judged whole: one bad stop, one
|
|
332
345
|
unknown key, two kinds at once, and the whole value emits no rule and no class name.
|
|
333
|
-
- It writes `background-image`, so `bgGradient` and `bgImage` are the same property.
|
|
346
|
+
- It writes `background-image`, so `bgGradient` and `bgImage` are the same property. `bgGradient` is declared
|
|
347
|
+
later and wins, so a variant or a design takes a gradient off with `bgGradient: 'none'`, never `bgImage: 'none'`.
|
|
348
|
+
- `letterSpacing` is pixels as a number, and Tailwind's tracking names in `em` — `'tighter'` (-0.05em), `'tight'`,
|
|
349
|
+
`'normal'`, `'wide'`, `'wider'`, `'widest'` (0.1em) — which is what a display heading wants at every size.
|
|
334
350
|
|
|
335
351
|
**Four shadows stack**, because each sets its own custom property and all four write one composed
|
|
336
352
|
`box-shadow`. A ring and an elevation coexist instead of the last one winning:
|
|
@@ -1094,6 +1110,40 @@ const harbor = Box.createComponents({ button: { styles: { borderRadius: 0 } } },
|
|
|
1094
1110
|
- **A Server Component cannot read the provider.** A client component under it can.
|
|
1095
1111
|
- **Types for two designs that both name a component**: `interface ComponentsTypes extends MergeComponentsAndVariants<[typeof aurora, typeof harbor]> {}` (from `@box-kite/core/types`). Extending two `ExtractComponentsAndVariants` that disagree on `button` is an interface conflict.
|
|
1096
1112
|
|
|
1113
|
+
### Box.components(styles, { design }) — A Design Chosen in CSS
|
|
1114
|
+
|
|
1115
|
+
A registry is chosen by React context, so a prerendered page can only switch to it after hydration — a flash, and a
|
|
1116
|
+
hydration mismatch if the client renders it first. A **named design** is chosen by an attribute instead: its styles are
|
|
1117
|
+
merged over the app's components and applied wherever an ancestor carries `data-design="<name>"`, so a stored choice
|
|
1118
|
+
written onto `<html>` before the first paint is the whole fix.
|
|
1119
|
+
|
|
1120
|
+
```tsx
|
|
1121
|
+
Box.components({ button: { styles: { borderRadius: 2.5 } }, dialog: { styles: { borderRadius: 5, p: 7 } } }, { design: 'ember' });
|
|
1122
|
+
|
|
1123
|
+
<Box.Theme
|
|
1124
|
+
use="global"
|
|
1125
|
+
design="classic"
|
|
1126
|
+
designStorageKey="design"
|
|
1127
|
+
globalStyles={{ dataAttr: { 'design=ember': { vars: Box.palette({ accent: 'orange', base: 'stone' }) } } }}
|
|
1128
|
+
>
|
|
1129
|
+
<App />
|
|
1130
|
+
</Box.Theme>;
|
|
1131
|
+
|
|
1132
|
+
const [design, setDesign] = Box.useDesign(); // setDesign(null) goes back to the design prop
|
|
1133
|
+
```
|
|
1134
|
+
|
|
1135
|
+
- **Both designs are in the CSS.** A Box whose component a design changes carries the design's whole class list beside its
|
|
1136
|
+
own, each rule one class more specific — so every state the app's design styles (a theme, a hover, a variant) is
|
|
1137
|
+
outranked by the same state of the design. A component the design leaves alone costs nothing.
|
|
1138
|
+
- **To take something back off, write its `none`** (`shadow: 'none'`, `bgGradient: 'none'`): a design merges, it cannot delete a key.
|
|
1139
|
+
- **A design nested in another stops the outer one** — a `data-design="classic"` preview inside an Ember page is Classic.
|
|
1140
|
+
The palette is `vars`, which inherit, so that wrapper declares its own `Box.palette()` too.
|
|
1141
|
+
- **Props still win**, and a Box under `<Box.Components value>` resolves against that registry and no named design.
|
|
1142
|
+
- `Box.Theme` writes `data-design` on `<html>` (`use="global"`) or on its wrapper, restores `designStorageKey` after
|
|
1143
|
+
hydration without writing the default over a value a pre-paint script set, and pauses transitions for the switch.
|
|
1144
|
+
`applyDesignToElement` is the framework-free half, in `@box-kite/core`.
|
|
1145
|
+
- **A part can `extends` too**: `trigger: { extends: 'button' }` or `'dialog.title'`. It used to be silently ignored.
|
|
1146
|
+
|
|
1097
1147
|
---
|
|
1098
1148
|
|
|
1099
1149
|
## Extension System
|
|
@@ -2564,7 +2614,7 @@ function TrendCell({ cell }: { cell: CellModel<Row> }) {
|
|
|
2564
2614
|
4. **fontSize divider is 16** (not 4). `fontSize={14}` → 14px
|
|
2565
2615
|
5. **Spacing divider is 4**. `p={4}` → 16px (1rem)
|
|
2566
2616
|
6. **Border width and lineHeight are direct px**. `b={1}` → 1px. **borderRadius uses divider 4**: `borderRadius={2}` → 8px
|
|
2567
|
-
7. **Colors are Tailwind's OKLCH palette**: `'gray-500'`, `'blue-600'` — 26 families × 11 steps, and an opacity modifier on any of them: `bgColor="blue-500/40"` (a `color-mix`, not `opacity`)
|
|
2617
|
+
7. **Colors are Tailwind's OKLCH palette**: `'gray-500'`, `'blue-600'` — 26 families × 11 steps, and an opacity modifier on any of them: `bgColor="blue-500/40"` (a `color-mix`, not `opacity`). The built-in components are drawn in two more, `accent` and `base`, which `Box.palette()` repoints
|
|
2568
2618
|
8. **Breakpoints are mobile-first**: base → sm → md → lg → xl → xxl
|
|
2569
2619
|
9. **Theme styles nest**: `theme={{ dark: { hover: { ... } } }}`
|
|
2570
2620
|
10. **HTML attributes go in `props` prop**: `<Link props={{ href: '/about' }}>` not `<Link href>`. `data-*` and `aria-*` go there too — a `data-state` written at the top level typechecks and is then dropped
|
package/BOX_KITE_AI_CONTEXT.md
CHANGED
|
@@ -307,6 +307,19 @@ Any colour value takes a slash and a percentage:
|
|
|
307
307
|
- A token the palette does not have, or a percentage outside 0–100, produces **no rule and no class
|
|
308
308
|
name** — the same silence every unmatched value gets.
|
|
309
309
|
|
|
310
|
+
**Two more families, `accent` and `base`, are what every built-in component is drawn in.** They start as
|
|
311
|
+
copies of `indigo` and `gray`, so nothing changes until one is pointed somewhere. `Box.palette()` returns the
|
|
312
|
+
`vars` record that does it, for an element and its subtree — a family by name, or a ramp of your own:
|
|
313
|
+
|
|
314
|
+
```tsx
|
|
315
|
+
<Box vars={Box.palette({ accent: 'orange', base: 'stone' })} /> // every Button inside is orange
|
|
316
|
+
<Box vars={Box.palette({ accent: { 500: 'oklch(68% .19 42)' } })} /> // a step left out keeps its default
|
|
317
|
+
<Box theme={{ dark: { vars: Box.palette({ accent: 'amber' }) } }} /> // nests like any vars
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
Write `accent-*`/`base-*` in your own components when they should follow a design, and a named family when the
|
|
321
|
+
colour is the content (a status, a chart series). A class built from them reads `bgColor-accent-500`.
|
|
322
|
+
|
|
310
323
|
### Gradients, shadows and rings
|
|
311
324
|
|
|
312
325
|
A gradient is a **value**, written as a record — so its stops are palette tokens, it takes the opacity
|
|
@@ -330,7 +343,10 @@ modifier, it is themed, and two elements asking for the same one share a class.
|
|
|
330
343
|
- A stop is any colour value — a token, `blue-500/40`, a system colour, `var(--chart-1)` — or a
|
|
331
344
|
`[colour, position]` pair. **Two stops minimum**, and the record is judged whole: one bad stop, one
|
|
332
345
|
unknown key, two kinds at once, and the whole value emits no rule and no class name.
|
|
333
|
-
- It writes `background-image`, so `bgGradient` and `bgImage` are the same property.
|
|
346
|
+
- It writes `background-image`, so `bgGradient` and `bgImage` are the same property. `bgGradient` is declared
|
|
347
|
+
later and wins, so a variant or a design takes a gradient off with `bgGradient: 'none'`, never `bgImage: 'none'`.
|
|
348
|
+
- `letterSpacing` is pixels as a number, and Tailwind's tracking names in `em` — `'tighter'` (-0.05em), `'tight'`,
|
|
349
|
+
`'normal'`, `'wide'`, `'wider'`, `'widest'` (0.1em) — which is what a display heading wants at every size.
|
|
334
350
|
|
|
335
351
|
**Four shadows stack**, because each sets its own custom property and all four write one composed
|
|
336
352
|
`box-shadow`. A ring and an elevation coexist instead of the last one winning:
|
|
@@ -1094,6 +1110,40 @@ const harbor = Box.createComponents({ button: { styles: { borderRadius: 0 } } },
|
|
|
1094
1110
|
- **A Server Component cannot read the provider.** A client component under it can.
|
|
1095
1111
|
- **Types for two designs that both name a component**: `interface ComponentsTypes extends MergeComponentsAndVariants<[typeof aurora, typeof harbor]> {}` (from `@box-kite/core/types`). Extending two `ExtractComponentsAndVariants` that disagree on `button` is an interface conflict.
|
|
1096
1112
|
|
|
1113
|
+
### Box.components(styles, { design }) — A Design Chosen in CSS
|
|
1114
|
+
|
|
1115
|
+
A registry is chosen by React context, so a prerendered page can only switch to it after hydration — a flash, and a
|
|
1116
|
+
hydration mismatch if the client renders it first. A **named design** is chosen by an attribute instead: its styles are
|
|
1117
|
+
merged over the app's components and applied wherever an ancestor carries `data-design="<name>"`, so a stored choice
|
|
1118
|
+
written onto `<html>` before the first paint is the whole fix.
|
|
1119
|
+
|
|
1120
|
+
```tsx
|
|
1121
|
+
Box.components({ button: { styles: { borderRadius: 2.5 } }, dialog: { styles: { borderRadius: 5, p: 7 } } }, { design: 'ember' });
|
|
1122
|
+
|
|
1123
|
+
<Box.Theme
|
|
1124
|
+
use="global"
|
|
1125
|
+
design="classic"
|
|
1126
|
+
designStorageKey="design"
|
|
1127
|
+
globalStyles={{ dataAttr: { 'design=ember': { vars: Box.palette({ accent: 'orange', base: 'stone' }) } } }}
|
|
1128
|
+
>
|
|
1129
|
+
<App />
|
|
1130
|
+
</Box.Theme>;
|
|
1131
|
+
|
|
1132
|
+
const [design, setDesign] = Box.useDesign(); // setDesign(null) goes back to the design prop
|
|
1133
|
+
```
|
|
1134
|
+
|
|
1135
|
+
- **Both designs are in the CSS.** A Box whose component a design changes carries the design's whole class list beside its
|
|
1136
|
+
own, each rule one class more specific — so every state the app's design styles (a theme, a hover, a variant) is
|
|
1137
|
+
outranked by the same state of the design. A component the design leaves alone costs nothing.
|
|
1138
|
+
- **To take something back off, write its `none`** (`shadow: 'none'`, `bgGradient: 'none'`): a design merges, it cannot delete a key.
|
|
1139
|
+
- **A design nested in another stops the outer one** — a `data-design="classic"` preview inside an Ember page is Classic.
|
|
1140
|
+
The palette is `vars`, which inherit, so that wrapper declares its own `Box.palette()` too.
|
|
1141
|
+
- **Props still win**, and a Box under `<Box.Components value>` resolves against that registry and no named design.
|
|
1142
|
+
- `Box.Theme` writes `data-design` on `<html>` (`use="global"`) or on its wrapper, restores `designStorageKey` after
|
|
1143
|
+
hydration without writing the default over a value a pre-paint script set, and pauses transitions for the switch.
|
|
1144
|
+
`applyDesignToElement` is the framework-free half, in `@box-kite/core`.
|
|
1145
|
+
- **A part can `extends` too**: `trigger: { extends: 'button' }` or `'dialog.title'`. It used to be silently ignored.
|
|
1146
|
+
|
|
1097
1147
|
---
|
|
1098
1148
|
|
|
1099
1149
|
## Extension System
|
|
@@ -2564,7 +2614,7 @@ function TrendCell({ cell }: { cell: CellModel<Row> }) {
|
|
|
2564
2614
|
4. **fontSize divider is 16** (not 4). `fontSize={14}` → 14px
|
|
2565
2615
|
5. **Spacing divider is 4**. `p={4}` → 16px (1rem)
|
|
2566
2616
|
6. **Border width and lineHeight are direct px**. `b={1}` → 1px. **borderRadius uses divider 4**: `borderRadius={2}` → 8px
|
|
2567
|
-
7. **Colors are Tailwind's OKLCH palette**: `'gray-500'`, `'blue-600'` — 26 families × 11 steps, and an opacity modifier on any of them: `bgColor="blue-500/40"` (a `color-mix`, not `opacity`)
|
|
2617
|
+
7. **Colors are Tailwind's OKLCH palette**: `'gray-500'`, `'blue-600'` — 26 families × 11 steps, and an opacity modifier on any of them: `bgColor="blue-500/40"` (a `color-mix`, not `opacity`). The built-in components are drawn in two more, `accent` and `base`, which `Box.palette()` repoints
|
|
2568
2618
|
8. **Breakpoints are mobile-first**: base → sm → md → lg → xl → xxl
|
|
2569
2619
|
9. **Theme styles nest**: `theme={{ dark: { hover: { ... } } }}`
|
|
2570
2620
|
10. **HTML attributes go in `props` prop**: `<Link props={{ href: '/about' }}>` not `<Link href>`. `data-*` and `aria-*` go there too — a `data-state` written at the top level typechecks and is then dropped
|
package/box.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require("./rolldown-runtime.cjs"),t=require("./react-shared.cjs"),n=require("./client.cjs");let r=require("react");r=e.t(r,1);let i=require("@box-kite/core");function a({tag:e,tagProps:t,render:n}){let[i,a]=(0,r.useState)(!1);return r.default.createElement(e,{...t,onMouseEnter:()=>a(!0),onMouseLeave:()=>a(!1)},n({isHover:i}))}function o(e,i){let{tag:o=`div`,children:s}=e,{classNames:c,styleElements:l}=n.i(e,o===`svg`),u=t.d(e,c);i&&(u.ref=i);let d=typeof s==`function`?r.default.createElement(a,{tag:o,tagProps:u,render:s}):r.default.createElement(o,u,s);return l?r.default.createElement(r.default.Fragment,null,l,d):d}var s=t.f(o,`Box`);s.extend=i.BoxExtends.extend,s.components=i.BoxExtends.components,s.createComponents=i.BoxExtends.createComponents,s.Components=n.o,s.keyframes=i.BoxExtends.keyframes,s.spring=i.Springs.spring,s.Theme=n.n,s.useTheme=n.n.useTheme,s.getVariableValue=e=>(0,i.getDefaultEngine)().getVariableValue(e),s.configure=n.r.configure,s.viewTransition=i.startViewTransition;function c(e,r){return t.p(n.i(e,r?.svg===!0),e.className)}exports.default=s,exports.useBoxElement=o,exports.useClassNames=c,exports.useVisibility=n.a;
|
|
1
|
+
Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require("./rolldown-runtime.cjs"),t=require("./react-shared.cjs"),n=require("./client.cjs");let r=require("react");r=e.t(r,1);let i=require("@box-kite/core");function a({tag:e,tagProps:t,render:n}){let[i,a]=(0,r.useState)(!1);return r.default.createElement(e,{...t,onMouseEnter:()=>a(!0),onMouseLeave:()=>a(!1)},n({isHover:i}))}function o(e,i){let{tag:o=`div`,children:s}=e,{classNames:c,styleElements:l}=n.i(e,o===`svg`),u=t.d(e,c);i&&(u.ref=i);let d=typeof s==`function`?r.default.createElement(a,{tag:o,tagProps:u,render:s}):r.default.createElement(o,u,s);return l?r.default.createElement(r.default.Fragment,null,l,d):d}var s=t.f(o,`Box`);s.extend=i.BoxExtends.extend,s.components=i.BoxExtends.components,s.palette=i.BoxExtends.palette,s.createComponents=i.BoxExtends.createComponents,s.Components=n.o,s.keyframes=i.BoxExtends.keyframes,s.spring=i.Springs.spring,s.Theme=n.n,s.useTheme=n.n.useTheme,s.useDesign=n.n.useDesign,s.getVariableValue=e=>(0,i.getDefaultEngine)().getVariableValue(e),s.configure=n.r.configure,s.viewTransition=i.startViewTransition;function c(e,r){return t.p(n.i(e,r?.svg===!0),e.className)}exports.default=s,exports.useBoxElement=o,exports.useClassNames=c,exports.useVisibility=n.a;
|
package/box.d.ts
CHANGED
|
@@ -21,6 +21,8 @@ interface BoxType {
|
|
|
21
21
|
<TTag extends keyof React.JSX.IntrinsicElements = 'div', TKey extends keyof ComponentsAndVariants = never>(props: BoxCoreProps<TTag, TKey> & RefAttributes<ExtractElementFromTag<TTag>>): React.ReactNode;
|
|
22
22
|
extend: typeof BoxExtends.extend;
|
|
23
23
|
components: typeof BoxExtends.components;
|
|
24
|
+
/** The `vars` record that points the components' `accent` and `base` families at others, for an element and its subtree. */
|
|
25
|
+
palette: typeof BoxExtends.palette;
|
|
24
26
|
/** A design for one subtree, registered nowhere: hand it to `<Box.Components value>` or `<Box.Theme components>`. */
|
|
25
27
|
createComponents: typeof BoxExtends.createComponents;
|
|
26
28
|
/** Every Box below resolves its `component` against this registry instead of the app's `Box.components()`. */
|
|
@@ -30,6 +32,8 @@ interface BoxType {
|
|
|
30
32
|
spring: typeof Springs.spring;
|
|
31
33
|
Theme: typeof Theme;
|
|
32
34
|
useTheme: typeof Theme.useTheme;
|
|
35
|
+
/** Read the design the nearest `<Box.Theme>` draws in, and set it — `data-design` on its root. */
|
|
36
|
+
useDesign: typeof Theme.useDesign;
|
|
33
37
|
getVariableValue: (name: string) => string;
|
|
34
38
|
/** Explicit engine configuration (class-name hashing, style sink). Call once, before the first render. */
|
|
35
39
|
configure: typeof StylesContext.configure;
|
|
@@ -60,3 +64,4 @@ export declare function useClassNames<TKey extends keyof ComponentsAndVariants =
|
|
|
60
64
|
}): BoxClassNames;
|
|
61
65
|
export { useVisibility };
|
|
62
66
|
export type { BoxClassNames, BoxClassNameProps };
|
|
67
|
+
export type { BoxComponentStyles, BoxStyleProps } from '@box-kite/core/types';
|
package/box.mjs
CHANGED
|
@@ -22,7 +22,7 @@ function h(t, n) {
|
|
|
22
22
|
return s ? c.createElement(c.Fragment, null, s, u) : u;
|
|
23
23
|
}
|
|
24
24
|
var g = t(h, "Box");
|
|
25
|
-
g.extend = u.extend, g.components = u.components, g.createComponents = u.createComponents, g.Components = o, g.keyframes = u.keyframes, g.spring = d.spring, g.Theme = a, g.useTheme = a.useTheme, g.getVariableValue = (e) => f().getVariableValue(e), g.configure = s.configure, g.viewTransition = p;
|
|
25
|
+
g.extend = u.extend, g.components = u.components, g.palette = u.palette, g.createComponents = u.createComponents, g.Components = o, g.keyframes = u.keyframes, g.spring = d.spring, g.Theme = a, g.useTheme = a.useTheme, g.useDesign = a.useDesign, g.getVariableValue = (e) => f().getVariableValue(e), g.configure = s.configure, g.viewTransition = p;
|
|
26
26
|
function _(e, t) {
|
|
27
27
|
return n(i(e, t?.svg === !0), e.className);
|
|
28
28
|
}
|
package/client.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const e=require("./rolldown-runtime.cjs"),t=require("./react-shared.cjs"),n=require("./platform.cjs"),r=require("./effects.cjs"),i=require("./box.cjs");let a=require("react");a=e.t(a,1);let o=require("@box-kite/core"),s=require("react/jsx-runtime"),c=require("react-dom");var l=`[box-kite] The client build was loaded into a React Server Component graph, where React has no createContext. Import '@box-kite/react' by its package name — the react-server condition resolves it to a Box that renders on the server — and import the components that hold state (Dropdown, Tooltip, DataGrid, Checkbox, Select, Form) from a 'use client' module. See https://github.com/box-kite/box-kite#react-server-components-react-19`;function u(e){if(typeof e.createContext!=`function`)throw Error(l)}u(a.default);var d=a.default.createContext(void 0);function f({value:e,children:t}){return(0,s.jsx)(d.Provider,{value:e,children:t})}function p(e){let{node:t=null,event:r=`click`,hideOnScroll:i=!1,hideOnResize:o=!1,hideOnEscape:s=!0}=e??{},[c,l]=(0,a.useState)(!1),u=(0,a.useRef)(null);return(0,a.useEffect)(()=>{function e(e){let r=t??u.current;r&&!n.u(e,[r])&&l(!1)}function a(){l(!1)}function d(e){e.key===`Escape`&&l(!1)}let f=new AbortController;return c&&(window.addEventListener(r,e,f),s&&window.addEventListener(`keydown`,d,f),o&&window.addEventListener(`resize`,a,f),i&&window.addEventListener(`scroll`,e,{signal:f.signal,capture:!0})),()=>{f.abort()}},[t,c,r,s,o,i]),[c,l,u]}var m=r.t;function h(e,n){let{classNames:r,signature:i,styleElements:s}=t.l(e,n,(0,a.useContext)(d));return m(()=>{(0,o.getDefaultEngine)().flushSync()},[i??e]),{classNames:r,styleElements:s}}function g(e,n){let r=e?(0,o.getDefaultEngine)().addGlobalStyles(e,n):void 0;return m(()=>{(0,o.getDefaultEngine)().flushSync()},[e,n]),t.u(r)}var _;(function(e){function t(){(0,o.getDefaultEngine)().flushSync()}e.flushSync=t;function n(){(0,o.getDefaultEngine)().clear()}e.clear=n;function r(){return(0,o.getDefaultEngine)().getStyles()}e.getStyles=r;function i(){return(0,o.getDefaultEngine)().getStyleTag()}e.getStyleTag=i;function a(){return(0,o.getDefaultEngine)().styleElementId}e.styleElementId=a;function s(e){(0,o.getDefaultEngine)().configure(e)}e.configure=s})(_||={}),u(a.default);var v=a.default.createContext({theme:``,setTheme:()=>{}});function y(e){let{theme:t,use:n=`local`,storageKey:l,globalStyles:u,viewTransition:d,components:p}=e,
|
|
1
|
+
const e=require("./rolldown-runtime.cjs"),t=require("./react-shared.cjs"),n=require("./platform.cjs"),r=require("./effects.cjs"),i=require("./box.cjs");let a=require("react");a=e.t(a,1);let o=require("@box-kite/core"),s=require("react/jsx-runtime"),c=require("react-dom");var l=`[box-kite] The client build was loaded into a React Server Component graph, where React has no createContext. Import '@box-kite/react' by its package name — the react-server condition resolves it to a Box that renders on the server — and import the components that hold state (Dropdown, Tooltip, DataGrid, Checkbox, Select, Form) from a 'use client' module. See https://github.com/box-kite/box-kite#react-server-components-react-19`;function u(e){if(typeof e.createContext!=`function`)throw Error(l)}u(a.default);var d=a.default.createContext(void 0);function f({value:e,children:t}){return(0,s.jsx)(d.Provider,{value:e,children:t})}function p(e){let{node:t=null,event:r=`click`,hideOnScroll:i=!1,hideOnResize:o=!1,hideOnEscape:s=!0}=e??{},[c,l]=(0,a.useState)(!1),u=(0,a.useRef)(null);return(0,a.useEffect)(()=>{function e(e){let r=t??u.current;r&&!n.u(e,[r])&&l(!1)}function a(){l(!1)}function d(e){e.key===`Escape`&&l(!1)}let f=new AbortController;return c&&(window.addEventListener(r,e,f),s&&window.addEventListener(`keydown`,d,f),o&&window.addEventListener(`resize`,a,f),i&&window.addEventListener(`scroll`,e,{signal:f.signal,capture:!0})),()=>{f.abort()}},[t,c,r,s,o,i]),[c,l,u]}var m=r.t;function h(e,n){let{classNames:r,signature:i,styleElements:s}=t.l(e,n,(0,a.useContext)(d));return m(()=>{(0,o.getDefaultEngine)().flushSync()},[i??e]),{classNames:r,styleElements:s}}function g(e,n){let r=e?(0,o.getDefaultEngine)().addGlobalStyles(e,n):void 0;return m(()=>{(0,o.getDefaultEngine)().flushSync()},[e,n]),t.u(r)}var _;(function(e){function t(){(0,o.getDefaultEngine)().flushSync()}e.flushSync=t;function n(){(0,o.getDefaultEngine)().clear()}e.clear=n;function r(){return(0,o.getDefaultEngine)().getStyles()}e.getStyles=r;function i(){return(0,o.getDefaultEngine)().getStyleTag()}e.getStyleTag=i;function a(){return(0,o.getDefaultEngine)().styleElementId}e.styleElementId=a;function s(e){(0,o.getDefaultEngine)().configure(e)}e.configure=s})(_||={}),u(a.default);var v=a.default.createContext({theme:``,setTheme:()=>{},setDesign:()=>{}});function y(e){let{theme:t,use:n=`local`,storageKey:l,globalStyles:u,viewTransition:d,components:p,design:m,designStorageKey:h}=e,_=p?(0,s.jsx)(f,{value:p,children:e.children}):e.children,y=g(n===`global`?u:void 0,`html`),[b,x]=(0,a.useState)(t??o.defaultThemeName),[S,C]=(0,a.useState)(t!==void 0),w=(0,a.useRef)(null),T=(0,a.useRef)(b),E=(0,a.useRef)(null),D=(0,a.useRef)(null),O=(0,a.useRef)(void 0),k=(0,a.useCallback)(e=>{if(!d)return e();let t=(0,o.transitionTheme)(()=>(0,c.flushSync)(e),d===`reveal`?`reveal`:`fade`);O.current=t.finished,t.finished.then(()=>O.current=void 0,()=>O.current=void 0)},[d]),A=(0,a.useCallback)(e=>k(()=>{e===null?(l&&(0,o.clearStoredTheme)(l),C(!1)):(l&&(0,o.writeStoredTheme)(l,e),x(e),C(!0))}),[l,k]),[j,M]=(0,a.useState)(m),[N,P]=(0,a.useState)(m);m!==N&&(P(m),M(m));let F=(0,a.useCallback)(e=>k(()=>{D.current??=(0,o.pauseTransitions)(),h&&(e===null?o.clearStoredTheme:o.writeStoredTheme)(h,e),M(e??m)}),[m,h,k]),I=(0,a.useRef)(null);(0,a.useLayoutEffect)(()=>{let e=h?(0,o.readStoredTheme)(h):null;e&&(I.current=e,M(e))},[h]),(0,a.useLayoutEffect)(()=>{if(I.current!==null&&I.current!==j)return;I.current=null;let e=n===`global`&&j?(0,o.documentRoot)():null,t=e?(0,o.applyDesignToElement)(e,j):void 0;return D.current?.(O.current),D.current=null,t},[j,n]);let L=d===`reveal`;(0,a.useEffect)(()=>L?(0,o.prepareReveal)():void 0,[L]);let[R,z]=(0,a.useState)(t);t!==R&&(z(t),t===void 0?C(!1):(x(t),C(!0))),(0,a.useLayoutEffect)(()=>{if(S)return;let e=l?(0,o.readStoredTheme)(l):null,t=e??(0,o.getSystemTheme)();if(t!==T.current&&(w.current=t),x(t),e){C(!0);return}return(0,o.watchSystemTheme)(x)},[S,l]),r.t(()=>{b!==T.current&&(E.current??=(0,o.pauseTransitions)())},[b]),(0,a.useLayoutEffect)(()=>{if(T.current=b,w.current!==null&&w.current!==b)return;w.current=null;let e=E.current;E.current=null;let t=n===`global`?(0,o.documentRoot)():null,r=t?(0,o.applyThemeToElement)(t,b):void 0;return e?.(O.current),r},[b,n]);let B=(0,a.useMemo)(()=>({theme:b,setTheme:A,design:j,setDesign:F}),[b,A,j,F]);return n===`local`?(0,s.jsxs)(v.Provider,{value:B,children:[y,(0,s.jsx)(i.default,{className:b,props:{"data-theme":b,"data-design":j},children:_})]}):(0,s.jsxs)(v.Provider,{value:B,children:[y,_]})}(function(e){function t(){let{theme:e,setTheme:t}=(0,a.useContext)(v);return[e,t]}e.useTheme=t;function n(){let{design:e,setDesign:t}=(0,a.useContext)(v);return[e,t]}e.useDesign=n})(y||={});var b=y,x=new WeakMap;function S(e){let t=x.get(e);return t||(t=new Map,x.set(e,t)),t}function C(e=!0){let[t]=b.useTheme(),r=(0,a.useMemo)(()=>{if(!e)return null;let t=n.t();if(!t)return null;let r=`box-kite-portal`,i=t.getElementById(r);return i||(i=document.createElement(`div`),i.id=r,document.body.appendChild(i)),i},[e]);return(0,a.useLayoutEffect)(()=>{if(!t||!r)return;let e=S(r),n=e.get(t)??0;return e.set(t,n+1),n===0&&r.classList.add(t),()=>{let n=(e.get(t)??1)-1;n<=0?(e.delete(t),r.classList.remove(t)):e.set(t,n)}},[r,t]),r}Object.defineProperty(exports,"a",{enumerable:!0,get:function(){return p}}),Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return h}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return b}}),Object.defineProperty(exports,"o",{enumerable:!0,get:function(){return f}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return _}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return C}});
|
package/client.mjs
CHANGED
|
@@ -3,9 +3,9 @@ import { t as n, u as r } from "./platform.mjs";
|
|
|
3
3
|
import { t as i } from "./effects.mjs";
|
|
4
4
|
import a from "./box.mjs";
|
|
5
5
|
import o, { useCallback as s, useContext as c, useEffect as l, useLayoutEffect as u, useMemo as d, useRef as f, useState as p } from "react";
|
|
6
|
-
import {
|
|
7
|
-
import { jsx as
|
|
8
|
-
import { flushSync as
|
|
6
|
+
import { applyDesignToElement as m, applyThemeToElement as h, clearStoredTheme as g, defaultThemeName as _, documentRoot as v, getDefaultEngine as y, getSystemTheme as b, pauseTransitions as x, prepareReveal as S, readStoredTheme as C, transitionTheme as w, watchSystemTheme as T, writeStoredTheme as E } from "@box-kite/core";
|
|
7
|
+
import { jsx as D, jsxs as O } from "react/jsx-runtime";
|
|
8
|
+
import { flushSync as ee } from "react-dom";
|
|
9
9
|
//#region src/react/clientRuntime.ts
|
|
10
10
|
var k = "[box-kite] The client build was loaded into a React Server Component graph, where React has no createContext. Import '@box-kite/react' by its package name — the react-server condition resolves it to a Box that renders on the server — and import the components that hold state (Dropdown, Tooltip, DataGrid, Checkbox, Select, Form) from a 'use client' module. See https://github.com/box-kite/box-kite#react-server-components-react-19";
|
|
11
11
|
function A(e) {
|
|
@@ -18,7 +18,7 @@ var j = o.createContext(void 0);
|
|
|
18
18
|
//#endregion
|
|
19
19
|
//#region src/react/componentsProvider.tsx
|
|
20
20
|
function M({ value: e, children: t }) {
|
|
21
|
-
return /* @__PURE__ */
|
|
21
|
+
return /* @__PURE__ */ D(j.Provider, {
|
|
22
22
|
value: e,
|
|
23
23
|
children: t
|
|
24
24
|
});
|
|
@@ -64,16 +64,16 @@ var P = i;
|
|
|
64
64
|
function F(t, n) {
|
|
65
65
|
let { classNames: r, signature: i, styleElements: a } = e(t, n, c(j));
|
|
66
66
|
return P(() => {
|
|
67
|
-
|
|
67
|
+
y().flushSync();
|
|
68
68
|
}, [i ?? t]), {
|
|
69
69
|
classNames: r,
|
|
70
70
|
styleElements: a
|
|
71
71
|
};
|
|
72
72
|
}
|
|
73
73
|
function I(e, n) {
|
|
74
|
-
let r = e ?
|
|
74
|
+
let r = e ? y().addGlobalStyles(e, n) : void 0;
|
|
75
75
|
return P(() => {
|
|
76
|
-
|
|
76
|
+
y().flushSync();
|
|
77
77
|
}, [e, n]), t(r);
|
|
78
78
|
}
|
|
79
79
|
var L;
|
|
@@ -81,84 +81,110 @@ var L;
|
|
|
81
81
|
//#region src/react/theme/themeContext.ts
|
|
82
82
|
(function(e) {
|
|
83
83
|
function t() {
|
|
84
|
-
|
|
84
|
+
y().flushSync();
|
|
85
85
|
}
|
|
86
86
|
e.flushSync = t;
|
|
87
87
|
function n() {
|
|
88
|
-
|
|
88
|
+
y().clear();
|
|
89
89
|
}
|
|
90
90
|
e.clear = n;
|
|
91
91
|
function r() {
|
|
92
|
-
return
|
|
92
|
+
return y().getStyles();
|
|
93
93
|
}
|
|
94
94
|
e.getStyles = r;
|
|
95
95
|
function i() {
|
|
96
|
-
return
|
|
96
|
+
return y().getStyleTag();
|
|
97
97
|
}
|
|
98
98
|
e.getStyleTag = i;
|
|
99
99
|
function a() {
|
|
100
|
-
return
|
|
100
|
+
return y().styleElementId;
|
|
101
101
|
}
|
|
102
102
|
e.styleElementId = a;
|
|
103
103
|
function o(e) {
|
|
104
|
-
|
|
104
|
+
y().configure(e);
|
|
105
105
|
}
|
|
106
106
|
e.configure = o;
|
|
107
107
|
})(L ||= {}), A(o);
|
|
108
108
|
var R = o.createContext({
|
|
109
109
|
theme: "",
|
|
110
|
-
setTheme: () => {}
|
|
110
|
+
setTheme: () => {},
|
|
111
|
+
setDesign: () => {}
|
|
111
112
|
});
|
|
112
113
|
//#endregion
|
|
113
114
|
//#region src/react/theme/theme.tsx
|
|
114
115
|
function z(e) {
|
|
115
|
-
let { theme: t, use: n = "local", storageKey: r, globalStyles: o, viewTransition: c, components:
|
|
116
|
-
value:
|
|
116
|
+
let { theme: t, use: n = "local", storageKey: r, globalStyles: o, viewTransition: c, components: y, design: k, designStorageKey: A } = e, j = y ? /* @__PURE__ */ D(M, {
|
|
117
|
+
value: y,
|
|
117
118
|
children: e.children
|
|
118
|
-
}) : e.children,
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
119
|
+
}) : e.children, N = I(n === "global" ? o : void 0, "html"), [P, F] = p(t ?? _), [L, z] = p(t !== void 0), B = f(null), V = f(P), H = f(null), U = f(null), W = f(void 0), G = s((e) => {
|
|
120
|
+
if (!c) return e();
|
|
121
|
+
let t = w(() => ee(e), c === "reveal" ? "reveal" : "fade");
|
|
122
|
+
W.current = t.finished, t.finished.then(() => W.current = void 0, () => W.current = void 0);
|
|
123
|
+
}, [c]), K = s((e) => G(() => {
|
|
124
|
+
e === null ? (r && g(r), z(!1)) : (r && E(r, e), F(e), z(!0));
|
|
125
|
+
}), [r, G]), [q, J] = p(k), [Y, te] = p(k);
|
|
126
|
+
k !== Y && (te(k), J(k));
|
|
127
|
+
let X = s((e) => G(() => {
|
|
128
|
+
U.current ??= x(), A && (e === null ? g : E)(A, e), J(e ?? k);
|
|
129
|
+
}), [
|
|
130
|
+
k,
|
|
131
|
+
A,
|
|
132
|
+
G
|
|
133
|
+
]), Z = f(null);
|
|
134
|
+
u(() => {
|
|
135
|
+
let e = A ? C(A) : null;
|
|
136
|
+
e && (Z.current = e, J(e));
|
|
137
|
+
}, [A]), u(() => {
|
|
138
|
+
if (Z.current !== null && Z.current !== q) return;
|
|
139
|
+
Z.current = null;
|
|
140
|
+
let e = n === "global" && q ? v() : null, t = e ? m(e, q) : void 0;
|
|
141
|
+
return U.current?.(W.current), U.current = null, t;
|
|
142
|
+
}, [q, n]);
|
|
143
|
+
let Q = c === "reveal";
|
|
144
|
+
l(() => Q ? S() : void 0, [Q]);
|
|
145
|
+
let [ne, re] = p(t);
|
|
146
|
+
t !== ne && (re(t), t === void 0 ? z(!1) : (F(t), z(!0))), u(() => {
|
|
147
|
+
if (L) return;
|
|
148
|
+
let e = r ? C(r) : null, t = e ?? b();
|
|
149
|
+
if (t !== V.current && (B.current = t), F(t), e) {
|
|
150
|
+
z(!0);
|
|
134
151
|
return;
|
|
135
152
|
}
|
|
136
|
-
return
|
|
137
|
-
}, [
|
|
138
|
-
|
|
139
|
-
}, [
|
|
140
|
-
if (
|
|
141
|
-
|
|
142
|
-
let e =
|
|
143
|
-
|
|
144
|
-
let t = n === "global" ?
|
|
145
|
-
return e?.(
|
|
146
|
-
}, [
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
153
|
+
return T(F);
|
|
154
|
+
}, [L, r]), i(() => {
|
|
155
|
+
P !== V.current && (H.current ??= x());
|
|
156
|
+
}, [P]), u(() => {
|
|
157
|
+
if (V.current = P, B.current !== null && B.current !== P) return;
|
|
158
|
+
B.current = null;
|
|
159
|
+
let e = H.current;
|
|
160
|
+
H.current = null;
|
|
161
|
+
let t = n === "global" ? v() : null, r = t ? h(t, P) : void 0;
|
|
162
|
+
return e?.(W.current), r;
|
|
163
|
+
}, [P, n]);
|
|
164
|
+
let $ = d(() => ({
|
|
165
|
+
theme: P,
|
|
166
|
+
setTheme: K,
|
|
167
|
+
design: q,
|
|
168
|
+
setDesign: X
|
|
169
|
+
}), [
|
|
170
|
+
P,
|
|
171
|
+
K,
|
|
172
|
+
q,
|
|
173
|
+
X
|
|
174
|
+
]);
|
|
175
|
+
return n === "local" ? /* @__PURE__ */ O(R.Provider, {
|
|
176
|
+
value: $,
|
|
177
|
+
children: [N, /* @__PURE__ */ D(a, {
|
|
178
|
+
className: P,
|
|
179
|
+
props: {
|
|
180
|
+
"data-theme": P,
|
|
181
|
+
"data-design": q
|
|
182
|
+
},
|
|
183
|
+
children: j
|
|
155
184
|
})]
|
|
156
|
-
}) : /* @__PURE__ */
|
|
157
|
-
value:
|
|
158
|
-
|
|
159
|
-
setTheme: V
|
|
160
|
-
},
|
|
161
|
-
children: [k, v]
|
|
185
|
+
}) : /* @__PURE__ */ O(R.Provider, {
|
|
186
|
+
value: $,
|
|
187
|
+
children: [N, j]
|
|
162
188
|
});
|
|
163
189
|
}
|
|
164
190
|
(function(e) {
|
|
@@ -167,6 +193,11 @@ function z(e) {
|
|
|
167
193
|
return [e, t];
|
|
168
194
|
}
|
|
169
195
|
e.useTheme = t;
|
|
196
|
+
function n() {
|
|
197
|
+
let { design: e, setDesign: t } = c(R);
|
|
198
|
+
return [e, t];
|
|
199
|
+
}
|
|
200
|
+
e.useDesign = n;
|
|
170
201
|
})(z ||= {});
|
|
171
202
|
var B = z, V = /* @__PURE__ */ new WeakMap();
|
|
172
203
|
function H(e) {
|