@box-kite/react 2.1.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/rules/box-kite-rules.md +8 -2
- package/.claude/skills/box-kite/SKILL.md +11 -5
- package/.claude/skills/box-kite/references/patterns.md +1 -1
- package/.claude/skills/box-kite/references/styling.md +23 -0
- package/.cursor/rules/box-kite.mdc +9 -3
- package/AGENTS.md +9 -3
- package/BOX_AI_CONTEXT.md +171 -12
- package/BOX_KITE_AI_CONTEXT.md +171 -12
- package/README.md +2 -2
- package/box.cjs +1 -1
- package/box.d.ts +13 -2
- package/box.mjs +25 -18
- package/catalog.cjs +1 -1
- package/catalog.mjs +15 -1
- package/client.cjs +1 -1
- package/client.mjs +59 -51
- package/components/button.cjs +1 -1
- package/components/button.mjs +10 -14
- package/components/flex.cjs +1 -1
- package/components/flex.mjs +10 -13
- package/components/form.cjs +1 -1
- package/components/form.mjs +7 -7
- package/components/grid.cjs +1 -1
- package/components/grid.mjs +10 -13
- package/components/menu.cjs +1 -1
- package/components/menu.mjs +16 -16
- package/components/overlay.cjs +1 -1
- package/components/overlay.mjs +35 -34
- package/components/popover.cjs +1 -1
- package/components/popover.mjs +4 -4
- package/components/semantics.cjs +1 -1
- package/components/semantics.mjs +9 -13
- package/components/svg.cjs +1 -1
- package/components/svg.mjs +38 -44
- package/components/textarea.cjs +1 -1
- package/components/textarea.mjs +12 -16
- package/components/textbox.cjs +1 -1
- package/components/textbox.mjs +12 -16
- package/components/toaster.cjs +1 -1
- package/components/toaster.mjs +42 -43
- package/components/visuallyHidden.cjs +1 -1
- package/components/visuallyHidden.mjs +10 -13
- package/docs/mcp.md +6 -5
- package/docs/props.md +132 -20
- package/layer.cjs +1 -1
- package/layer.mjs +61 -59
- package/mcp/src/data.d.ts +1 -1
- package/mcp/src/styles.d.ts +2 -2
- package/mcp/src/vocabulary.d.ts +1 -1
- package/package.json +74 -48
- package/react/boxComponent.d.ts +10 -0
- package/react/popover/useTopLayer.d.ts +17 -0
- package/react/theme/theme.d.ts +10 -0
- package/react/useStyles.d.ts +2 -0
- package/react-shared.cjs +1 -1
- package/react-shared.mjs +44 -37
- package/rsc.cjs +1 -1
- package/rsc.d.ts +11 -1
- package/rsc.mjs +15 -12
- package/ssg.cjs +1 -1
- package/ssg.d.ts +8 -2
- package/ssg.mjs +13 -9
- package/utils/environment/environmentUtils.d.ts +5 -0
package/BOX_KITE_AI_CONTEXT.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @box-kite/react - AI Assistant Context
|
|
2
2
|
|
|
3
|
-
Runtime CSS-in-JS library. `Box` component accepts
|
|
3
|
+
Runtime CSS-in-JS library. `Box` component accepts 235 CSS props and generates CSS classes at runtime. Same prop values share a single class.
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -282,9 +282,13 @@ const { css, anchorProps, layerProps } = useAnchorPosition({ side: 'bottom', ali
|
|
|
282
282
|
The palette is **Tailwind 4.3's, in OKLCH**: twenty-six families of eleven steps (`50`–`950`) — the five
|
|
283
283
|
neutrals (`slate`, `gray`, `zinc`, `neutral`, `stone`), the four Tailwind 4.3 added (`mauve`, `mist`,
|
|
284
284
|
`olive`, `taupe`) and seventeen hues (`red`, `orange`, `amber`, `yellow`, `lime`, `green`, `emerald`,
|
|
285
|
-
`teal`, `cyan`, `sky`, `blue`, `indigo`, `violet`, `purple`, `fuchsia`, `pink`, `rose`).
|
|
286
|
-
CSS variable
|
|
287
|
-
nothing
|
|
285
|
+
`teal`, `cyan`, `sky`, `blue`, `indigo`, `violet`, `purple`, `fuchsia`, `pink`, `rose`). A token is a
|
|
286
|
+
CSS variable written **with its own value as the fallback** — `bgColor="sky-500"` is
|
|
287
|
+
`background-color: var(--sky-500,oklch(68.5% .169 237.3))` — so nothing is declared in `:root` (a late
|
|
288
|
+
`:root` insert recalculates every element on the page) and declaring `--sky-500` yourself still overrides
|
|
289
|
+
it. `var(--sky-500)` elsewhere in this file is that, shortened. Your own CSS cannot count on `--sky-500`
|
|
290
|
+
existing: hand it a variable of yours with `vars={{ brand: 'violet-500' }}` on an ancestor. A hand-written
|
|
291
|
+
`var(--sky-500)` _inside_ a Box value — `fill`, `vars`, `css`, a `Box.extend()` variable — gets the fallback too.
|
|
288
292
|
|
|
289
293
|
Any colour value takes a slash and a percentage:
|
|
290
294
|
|
|
@@ -642,6 +646,131 @@ const wobble = Box.spring({ stiffness: 120, damping: 8 });
|
|
|
642
646
|
|
|
643
647
|
---
|
|
644
648
|
|
|
649
|
+
### Scroll-driven animations
|
|
650
|
+
|
|
651
|
+
An animation's progress can come from a scroll position rather than a clock. There is no listener, no
|
|
652
|
+
`requestAnimationFrame` and no state: the browser runs it off the compositor, and the whole thing is props.
|
|
653
|
+
|
|
654
|
+
| Prop | CSS Property | Notes |
|
|
655
|
+
| ------------------------------------------- | ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
656
|
+
| `animationTimeline` | animation-timeline | `'none'`, `'auto'`, an anonymous timeline (`'scroll()'`, `'scroll(root block)'`, `'view()'`, `'view(inline 20%)'`) or a name a declaration below gave |
|
|
657
|
+
| `animationRange` | animation-range | One end or both: `'entry'`, `'cover 20%'`, `'entry 0% entry 100%'`, `'normal'` |
|
|
658
|
+
| `animationRangeStart` / `animationRangeEnd` | animation-range-start / -end | One end at a time. A named part of the pass with an optional offset, a bare length, or `'normal'` |
|
|
659
|
+
| `scrollTimeline` | scroll-timeline | Declares a named timeline on a **scroller**: `'page'` or `'page block'`. The `--` is optional and added for you |
|
|
660
|
+
| `scrollTimelineName` / `scrollTimelineAxis` | scroll-timeline-name / -axis | The two halves of that shorthand. Axis: `'block'`, `'inline'`, `'x'`, `'y'` |
|
|
661
|
+
| `viewTimeline` | view-timeline | Declares a named timeline on a **subject** — its own pass across the scrollport: `'card'` or `'card block'` |
|
|
662
|
+
| `viewTimelineName` / `viewTimelineAxis` | view-timeline-name / -axis | The two halves of that one |
|
|
663
|
+
| `viewTimelineInset` | view-timeline-inset | `'auto'`, or one or two lengths, shrinking the scrollport the pass is measured against |
|
|
664
|
+
| `timelineScope` | timeline-scope | Makes named timelines below this element reachable from anywhere else below it. Comma-separated |
|
|
665
|
+
|
|
666
|
+
The two anonymous timelines cover most of it and need nothing declared elsewhere:
|
|
667
|
+
|
|
668
|
+
```tsx
|
|
669
|
+
// A reading-progress bar: the page's own scroll, driving a scaleX from 0 to 1.
|
|
670
|
+
Box.keyframes({ progress: { from: { scale: 0 }, to: { scale: 1 } } });
|
|
671
|
+
|
|
672
|
+
<Box
|
|
673
|
+
position="fixed"
|
|
674
|
+
top={0}
|
|
675
|
+
insetX={0}
|
|
676
|
+
height={1}
|
|
677
|
+
bgColor="sky-500"
|
|
678
|
+
css={{ transformOrigin: 'left' }}
|
|
679
|
+
animationName="progress"
|
|
680
|
+
animationTimeline="scroll(root)"
|
|
681
|
+
animationFillMode="both"
|
|
682
|
+
motionReduce={{ animation: 'none' }}
|
|
683
|
+
/>;
|
|
684
|
+
|
|
685
|
+
// Reveal on scroll: this element's own pass, over the first 60% of its entry.
|
|
686
|
+
Box.keyframes({ 'fade-up': { from: { opacity: 0, translateY: 4 }, to: { opacity: 1, translateY: 0 } } });
|
|
687
|
+
|
|
688
|
+
<Box animationName="fade-up" animationTimeline="view()" animationRange="entry 0% entry 60%" motionReduce={{ animation: 'none' }}>
|
|
689
|
+
…
|
|
690
|
+
</Box>;
|
|
691
|
+
```
|
|
692
|
+
|
|
693
|
+
A **named** timeline is the two-sided form, for when the animated element is not inside the scroller:
|
|
694
|
+
|
|
695
|
+
```tsx
|
|
696
|
+
<Box timelineScope="page">
|
|
697
|
+
<Box height="fit-screen" overflow="auto" scrollTimeline="page block">
|
|
698
|
+
…
|
|
699
|
+
</Box>
|
|
700
|
+
<Box animationName="progress" animationTimeline="page" animationFillMode="both" />
|
|
701
|
+
</Box>
|
|
702
|
+
```
|
|
703
|
+
|
|
704
|
+
**Three things to know, and all three are traps:**
|
|
705
|
+
|
|
706
|
+
- **The CSS `animation` shorthand resets `animation-timeline`.** A timeline declared before it is
|
|
707
|
+
silently undone. The registry declares `animationTimeline` after `animation`, so writing both props is
|
|
708
|
+
safe in either order — but an `animation` written inside `css` sorts last and will undo it.
|
|
709
|
+
- **A scroll-driven animation has no duration**, so `--transitionTime` cannot zero it. It is the one kind
|
|
710
|
+
of motion in this library that does **not** stop itself under `prefers-reduced-motion`: pair it with
|
|
711
|
+
`motionReduce={{ animation: 'none' }}`, every time.
|
|
712
|
+
- **Where the browser has none, the declaration is dropped rather than the animation.** It then runs on the
|
|
713
|
+
document timeline over whatever duration it was given. Make the end state the resting state — with
|
|
714
|
+
`animationFillMode="both"` and a sequence that ends where the element belongs, a missing timeline degrades
|
|
715
|
+
to "already arrived" rather than to a loop. Chrome/Edge 115+, Safari 26+; Firefox is behind a flag.
|
|
716
|
+
|
|
717
|
+
---
|
|
718
|
+
|
|
719
|
+
### View transitions
|
|
720
|
+
|
|
721
|
+
The browser screenshots the page, runs the update, screenshots again, and cross-fades between the two —
|
|
722
|
+
so a change that was a jump becomes a transition with nothing animated by hand.
|
|
723
|
+
|
|
724
|
+
| Prop / API | What it does |
|
|
725
|
+
| ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
726
|
+
| `viewTransitionName` | Names this element, so it animates _from where it was to where it is_ instead of being cross-faded with the page. A `<custom-ident>`, **not** dashed |
|
|
727
|
+
| `viewTransitionClass` | A name shared by several elements, so `::view-transition-group(.card)` styles them together. Space-separated for more than one |
|
|
728
|
+
| `Box.viewTransition(update, options)` | Runs `update` inside `document.startViewTransition` where the browser has one, and plainly where it has not |
|
|
729
|
+
| `<Box.Theme viewTransition>` | That call around a theme change, `flushSync` included |
|
|
730
|
+
|
|
731
|
+
```tsx
|
|
732
|
+
const handle = Box.viewTransition(() => flushSync(() => setTab(next)), { types: ['forward'] });
|
|
733
|
+
await handle.finished;
|
|
734
|
+
```
|
|
735
|
+
|
|
736
|
+
```ts
|
|
737
|
+
interface ViewTransitionOptions {
|
|
738
|
+
/** `'skip'` (default) runs the update with no transition under reduced motion; `'play'` transitions anyway. */
|
|
739
|
+
reducedMotion?: 'skip' | 'play';
|
|
740
|
+
/** Types `:active-view-transition-type(name)` selects on, so forward and back can differ. */
|
|
741
|
+
types?: string[];
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
interface ViewTransitionHandle {
|
|
745
|
+
ready: Promise<void>;
|
|
746
|
+
finished: Promise<void>;
|
|
747
|
+
updateCallbackDone: Promise<void>;
|
|
748
|
+
skip(): void;
|
|
749
|
+
/** False when the browser had no API, or reduced motion skipped it. */
|
|
750
|
+
transitioned: boolean;
|
|
751
|
+
}
|
|
752
|
+
```
|
|
753
|
+
|
|
754
|
+
**Four things to know:**
|
|
755
|
+
|
|
756
|
+
- **In React the update has to be flushed.** The browser takes its second screenshot the moment the
|
|
757
|
+
callback returns, and a `setState` has not rendered by then — so a hand-rolled version captures the old
|
|
758
|
+
state twice and nothing appears to move. `flushSync` inside the callback is the fix, and
|
|
759
|
+
`<Box.Theme viewTransition>` is it already done for the one change every app has.
|
|
760
|
+
- **A name has to be unique in the document while the transition runs.** Two elements sharing one is how a
|
|
761
|
+
transition silently does nothing. The prop is for the handful of names a layout has (`header`, `main`);
|
|
762
|
+
a name **per list item** is a rule per item that is never freed, so that one goes in
|
|
763
|
+
`props={{ style: { viewTransitionName: id } }}` — the exception `useAnchorPosition`'s anchor name and a
|
|
764
|
+
`Slider` thumb already take.
|
|
765
|
+
- **Reduced motion skips the transition and keeps the update.** A whole-page cross-fade is exactly the
|
|
766
|
+
motion the preference is about. `{ reducedMotion: 'play' }` is the opt-out, for a change that is
|
|
767
|
+
unreadable without one.
|
|
768
|
+
- **The handle is the same shape either way**, so there is one code path: with no API, `finished` is an
|
|
769
|
+
already-resolved promise, `skip()` a no-op and `transitioned` false. `ready` rejects when a transition is
|
|
770
|
+
skipped, which is not an error — branch on `finished`.
|
|
771
|
+
|
|
772
|
+
---
|
|
773
|
+
|
|
645
774
|
## Pseudo-Classes, Breakpoints & Themes
|
|
646
775
|
|
|
647
776
|
```tsx
|
|
@@ -1119,24 +1248,41 @@ second argument for an element inside an `<svg>`. `<Icon>` is this hook plus tha
|
|
|
1119
1248
|
### Server-Side Rendering
|
|
1120
1249
|
|
|
1121
1250
|
```tsx
|
|
1122
|
-
import
|
|
1251
|
+
import Box from '@box-kite/react';
|
|
1252
|
+
import { getStyleTag, resetStyles } from '@box-kite/react/ssg';
|
|
1253
|
+
|
|
1254
|
+
Box.configure({ classNames: 'stable' }); // in the server AND in the browser entry
|
|
1123
1255
|
|
|
1124
1256
|
const html = renderToString(<App />); // any React server renderer
|
|
1125
|
-
const
|
|
1126
|
-
// <style id="box-kite-styles">{cssString}</style> in the document head
|
|
1257
|
+
const styleTag = getStyleTag(); // <style id="box-kite-styles" data-box-kite="…">…</style>, for the head
|
|
1127
1258
|
resetStyles(); // reset before the next request
|
|
1128
1259
|
```
|
|
1129
1260
|
|
|
1130
|
-
Or in one call, which injects the
|
|
1261
|
+
Or in one call, which injects the tag into the rendered `<head>` and resets afterwards:
|
|
1131
1262
|
|
|
1132
1263
|
```tsx
|
|
1133
1264
|
import { renderToStaticMarkup } from '@box-kite/react/ssg';
|
|
1134
1265
|
|
|
1135
|
-
const { html, styles } = renderToStaticMarkup(<App />);
|
|
1266
|
+
const { html, styles, styleTag } = renderToStaticMarkup(<App />);
|
|
1136
1267
|
```
|
|
1137
1268
|
|
|
1138
1269
|
No DOM is needed: with no `document` in the process the engine collects CSS in memory. Sequential
|
|
1139
|
-
requests are independent and identical markup gets identical class names.
|
|
1270
|
+
requests are independent and identical markup gets identical class names. `getStyles()` is the bare CSS.
|
|
1271
|
+
|
|
1272
|
+
**Adoption.** The `data-box-kite` attribute is a manifest — each rule's cascade position and a checksum
|
|
1273
|
+
of the classes it styles. On the first render the browser engine checks it against the sheet it parsed
|
|
1274
|
+
and takes the sheet over: every rule in it counts as generated, so hydration builds and inserts nothing
|
|
1275
|
+
for what the HTML already styled, and only rules the client adds afterwards are inserted, each in its
|
|
1276
|
+
cascade position. Two conditions:
|
|
1277
|
+
|
|
1278
|
+
| Condition | Why | If it does not hold |
|
|
1279
|
+
| --------------------------------------- | -------------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
|
|
1280
|
+
| `classNames: 'stable'` on both sides | the content-hashed names are how the browser recognises the server's rules | the sheet is left in place under no id and the engine writes its own after it |
|
|
1281
|
+
| the browser parsed every generated rule | an index is only trustworthy if nothing in between was dropped | same fallback |
|
|
1282
|
+
|
|
1283
|
+
Do **not** remove the server's `<style>` after hydration — it is the engine's own sheet now. Register
|
|
1284
|
+
the same `Box.extend()` props and `Box.keyframes()` sequences on both sides. `engine.getStyleTag()` is
|
|
1285
|
+
the same thing for `@box-kite/core`.
|
|
1140
1286
|
|
|
1141
1287
|
---
|
|
1142
1288
|
|
|
@@ -2139,7 +2285,7 @@ function TrendCell({ cell }: { cell: CellModel<Row> }) {
|
|
|
2139
2285
|
9. **Theme styles nest**: `theme={{ dark: { hover: { ... } } }}`
|
|
2140
2286
|
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
|
|
2141
2287
|
11. **Size shortcuts**: `width="fit"` = 100%, `width="fit-screen"` = 100vw, `width="1/2"` = 50%
|
|
2142
|
-
12. **Box is memoized** with `React.memo`
|
|
2288
|
+
12. **Box is memoized** with `React.memo`, and so are `Flex`, `H1`, `Button` and the rest. A component of your own that is a Box with defaults calls `useBoxElement({ p: 4, ...props }, ref)` from its own `forwardRef` rather than returning `<Box>` — one fiber instead of two
|
|
2143
2289
|
13. **`style` is top-level only** — never inside breakpoints (`sm={{ style: ... }}`), pseudo-classes, or theme objects. `css` is the one that nests: `sm={{ css: { objectPosition: 'top' } }}` is a rule
|
|
2144
2290
|
14. **A CSS variable is a prop**: `vars={{ 'color-x': 'sky-500' }}` declares `--color-x` for everything inside — and a third-party chart goes in `<ChartContainer series={['revenue']}>` so it names no colour at all
|
|
2145
2291
|
15. **All sizing props use divider 4** — `width`, `height`, `minWidth`, `maxWidth`, `minHeight`, `maxHeight` are NOT direct pixels. `height={10}` = 2.5rem = 40px
|
|
@@ -2896,6 +3042,19 @@ Also accepts: `data` (TRow[]), `value`/`defaultValue`, `label`/`labelProps`, `mu
|
|
|
2896
3042
|
3. **CSS variables**: In `:root` rules
|
|
2897
3043
|
4. **Theme issues**: Ensure `<Box.Theme>` wraps your app
|
|
2898
3044
|
5. **Layer theming**: a tooltip or dropdown popup stays where it was declared and inherits the theme; only the no-Popover-API fallback uses the `#box-kite-portal` container
|
|
3045
|
+
6. **Read the console first**: outside a production build the engine prints one `[box-kite]` warning per mistake that would otherwise be silent, each naming the fix:
|
|
3046
|
+
|
|
3047
|
+
| You wrote | The warning says |
|
|
3048
|
+
| -------------------------- | -------------------------------------------------------------------------- |
|
|
3049
|
+
| `bgColor="bleu-500"` | wrote no CSS … Did you mean `"blue-500"`? |
|
|
3050
|
+
| `opacity={50}` | wrote no CSS … It takes one of 0, 0.1, … 1 |
|
|
3051
|
+
| `<Link href="/about">` | `href` is an HTML attribute … write `props={{ href: ... }}` |
|
|
3052
|
+
| `fontSize={4}` | is 4px text … For 16px write `fontSize={16}` |
|
|
3053
|
+
| `lineHeight={1.5}` | is a 1.5px line … `lineHeight="font-size"`, or `css={{ lineHeight: 1.5 }}` |
|
|
3054
|
+
| `transitionDuration={0.3}` | is 0.3ms … For 0.3s write `transitionDuration={300}` |
|
|
3055
|
+
| `brightness={1.1}` | is 1.1% … For 110% write `brightness={110}` |
|
|
3056
|
+
|
|
3057
|
+
Once per value, and `Box.configure({ warnings: false })` silences them. In production a rejected value is dropped with nothing said, which is why `check_styles` (`@box-kite/mcp`) exists
|
|
2899
3058
|
|
|
2900
3059
|
---
|
|
2901
3060
|
|
|
@@ -3204,7 +3363,7 @@ allowed.tokens; // the colours, the @keyframes names and the style-tree nodes a
|
|
|
3204
3363
|
`DataGrid`'s `def` (required — the columns and the grid-wide flags) and `data`, `DashboardGrid`'s
|
|
3205
3364
|
`layout`/`defaultLayout`/`columns`, `Widget`'s `empty`, `ChartContainer`'s `series`. A column's nested
|
|
3206
3365
|
`columns`, and `dataSource`/`onCellEdit`/`rowDetail`/`treeData`, stay out — they are the app's to pass.
|
|
3207
|
-
- **The allow-list is the app's.** `catalog()` with no options is all 78 components and all
|
|
3366
|
+
- **The allow-list is the app's.** `catalog()` with no options is all 78 components and all 235 props —
|
|
3208
3367
|
~4.6 MB serialized. `include`, `exclude` and `styleProps` are how an app narrows it.
|
|
3209
3368
|
|
|
3210
3369
|
Full reference: `docs/catalog.md`.
|
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
[](https://github.com/box-kite/box-kite/actions/workflows/test.yml)
|
|
6
6
|
[](LICENSE)
|
|
7
7
|
|
|
8
|
-
`Box` is a single React component with
|
|
8
|
+
`Box` is a single React component with 235 typed CSS props. It generates the CSS for the values you
|
|
9
9
|
pass at runtime and caches every rule by its content, so the same value anywhere in the app reuses
|
|
10
10
|
one class — a project styles itself in TypeScript, with no CSS files to write and no class-name
|
|
11
11
|
convention to remember.
|
|
@@ -690,7 +690,7 @@ A complete page — props, pseudo-classes, breakpoints, themes, `extend`, `compo
|
|
|
690
690
|
|
|
691
691
|
## Architecture
|
|
692
692
|
|
|
693
|
-
The styling engine is framework-free. Everything that generates CSS — the
|
|
693
|
+
The styling engine is framework-free. Everything that generates CSS — the 235 prop definitions,
|
|
694
694
|
the value formatters, class-name generation, rule ordering, the style sinks (CSSOM, `textContent`,
|
|
695
695
|
string for SSR, style elements for React 19), the flush scheduler, CSS variables and the theme
|
|
696
696
|
runtime — lives in `src/core/` and imports no React at all. CI fails the build if it ever does
|
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(e,i){let{tag:
|
|
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.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;
|
package/box.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { default as React, RefAttributes } from 'react';
|
|
2
|
-
import { BoxExtends, Springs } from '@box-kite/core';
|
|
1
|
+
import { default as React, Ref, RefAttributes } from 'react';
|
|
2
|
+
import { BoxExtends, Springs, startViewTransition } from '@box-kite/core';
|
|
3
3
|
import { BoxClassNames } from './react/boxClassNames';
|
|
4
4
|
import { BoxClassNameProps, BoxCoreProps } from './react/boxProps';
|
|
5
5
|
import { default as useVisibility } from './react/hooks/useVisibility';
|
|
@@ -7,6 +7,15 @@ import { ExtractElementFromTag } from './react/reactTypes';
|
|
|
7
7
|
import { default as Theme } from './react/theme/theme';
|
|
8
8
|
import { StylesContext } from './react/useStyles';
|
|
9
9
|
import { ComponentsAndVariants } from '@box-kite/core/types';
|
|
10
|
+
/**
|
|
11
|
+
* Box's render as a hook, for a component that is a Box with defaults: called from its own `forwardRef`, it
|
|
12
|
+
* makes that component one fiber rather than a wrapper around a second one. `Flex`, `H1` and `Button` are this.
|
|
13
|
+
*
|
|
14
|
+
* ```tsx
|
|
15
|
+
* const Card = forwardRef<HTMLDivElement, BoxProps>((props, ref) => useBoxElement({ p: 4, ...props }, ref));
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export declare function useBoxElement<TTag extends keyof React.JSX.IntrinsicElements = 'div', TKey extends keyof ComponentsAndVariants = never>(props: BoxCoreProps<TTag, TKey>, ref?: Ref<ExtractElementFromTag<TTag>>): React.ReactNode;
|
|
10
19
|
interface BoxType {
|
|
11
20
|
<TTag extends keyof React.JSX.IntrinsicElements = 'div', TKey extends keyof ComponentsAndVariants = never>(props: BoxCoreProps<TTag, TKey> & RefAttributes<ExtractElementFromTag<TTag>>): React.ReactNode;
|
|
12
21
|
extend: typeof BoxExtends.extend;
|
|
@@ -19,6 +28,8 @@ interface BoxType {
|
|
|
19
28
|
getVariableValue: (name: string) => string;
|
|
20
29
|
/** Explicit engine configuration (class-name hashing, style sink). Call once, before the first render. */
|
|
21
30
|
configure: typeof StylesContext.configure;
|
|
31
|
+
/** Run a DOM change inside a view transition where the browser has one, and plainly where it has not. */
|
|
32
|
+
viewTransition: typeof startViewTransition;
|
|
22
33
|
}
|
|
23
34
|
declare const Box: BoxType;
|
|
24
35
|
export default Box;
|
package/box.mjs
CHANGED
|
@@ -1,23 +1,30 @@
|
|
|
1
|
-
import { d as e, f as t } from "./react-shared.mjs";
|
|
2
|
-
import { a as
|
|
3
|
-
import
|
|
4
|
-
import { BoxExtends as
|
|
1
|
+
import { d as e, f as t, p as n } from "./react-shared.mjs";
|
|
2
|
+
import { a as r, i, n as a, r as o } from "./client.mjs";
|
|
3
|
+
import s, { useState as c } from "react";
|
|
4
|
+
import { BoxExtends as l, Springs as u, getDefaultEngine as d, startViewTransition as f } from "@box-kite/core";
|
|
5
5
|
//#region src/box.ts
|
|
6
|
+
function p({ tag: e, tagProps: t, render: n }) {
|
|
7
|
+
let [r, i] = c(!1);
|
|
8
|
+
return s.createElement(e, {
|
|
9
|
+
...t,
|
|
10
|
+
onMouseEnter: () => i(!0),
|
|
11
|
+
onMouseLeave: () => i(!1)
|
|
12
|
+
}, n({ isHover: r }));
|
|
13
|
+
}
|
|
6
14
|
function m(t, n) {
|
|
7
|
-
let { tag:
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
return c ? o.createElement(o.Fragment, null, c, g) : g;
|
|
15
|
+
let { tag: r = "div", children: a } = t, { classNames: o, styleElements: c } = i(t, r === "svg"), l = e(t, o);
|
|
16
|
+
n && (l.ref = n);
|
|
17
|
+
let u = typeof a == "function" ? s.createElement(p, {
|
|
18
|
+
tag: r,
|
|
19
|
+
tagProps: l,
|
|
20
|
+
render: a
|
|
21
|
+
}) : s.createElement(r, l, a);
|
|
22
|
+
return c ? s.createElement(s.Fragment, null, c, u) : u;
|
|
16
23
|
}
|
|
17
|
-
var h =
|
|
18
|
-
h.
|
|
19
|
-
function g(e,
|
|
20
|
-
return
|
|
24
|
+
var h = t(m, "Box");
|
|
25
|
+
h.extend = l.extend, h.components = l.components, h.keyframes = l.keyframes, h.spring = u.spring, h.Theme = a, h.useTheme = a.useTheme, h.getVariableValue = (e) => d().getVariableValue(e), h.configure = o.configure, h.viewTransition = f;
|
|
26
|
+
function g(e, t) {
|
|
27
|
+
return n(i(e, t?.svg === !0), e.className);
|
|
21
28
|
}
|
|
22
29
|
//#endregion
|
|
23
|
-
export { h as default, g as useClassNames,
|
|
30
|
+
export { h as default, m as useBoxElement, g as useClassNames, r as useVisibility };
|