@inkra/react 0.0.0-stage → 0.1.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/LICENSE +21 -0
- package/README.md +213 -2
- package/THIRD_PARTY_NOTICES.md +39 -0
- package/Yozai-OFL.txt +94 -0
- package/dist/Button.d.ts +36 -0
- package/dist/Button.js +89 -0
- package/dist/PencilIcon.d.ts +22 -0
- package/dist/PencilIcon.js +212 -0
- package/dist/PencilLine.d.ts +10 -0
- package/dist/PencilLine.js +85 -0
- package/dist/PencilSurface.d.ts +19 -0
- package/dist/PencilSurface.js +19 -0
- package/dist/PencilText.d.ts +16 -0
- package/dist/PencilText.js +205 -0
- package/dist/accordion/Accordion.d.ts +27 -0
- package/dist/accordion/Accordion.js +40 -0
- package/dist/accordion/index.d.ts +2 -0
- package/dist/accordion/index.js +1 -0
- package/dist/assets/ui-hand-yozai.woff2 +0 -0
- package/dist/breadcrumb/index.d.ts +16 -0
- package/dist/breadcrumb/index.js +25 -0
- package/dist/calendar/index.d.ts +21 -0
- package/dist/calendar/index.js +41 -0
- package/dist/content/index.d.ts +106 -0
- package/dist/content/index.js +80 -0
- package/dist/day-agenda/index.d.ts +43 -0
- package/dist/day-agenda/index.js +47 -0
- package/dist/day-agenda/layout.d.ts +20 -0
- package/dist/day-agenda/layout.js +60 -0
- package/dist/display/index.d.ts +32 -0
- package/dist/display/index.js +59 -0
- package/dist/dropdown-menu/index.d.ts +34 -0
- package/dist/dropdown-menu/index.js +40 -0
- package/dist/form/EditablePencilText.d.ts +13 -0
- package/dist/form/EditablePencilText.js +312 -0
- package/dist/form/Field.d.ts +13 -0
- package/dist/form/Field.js +26 -0
- package/dist/form/Input.d.ts +27 -0
- package/dist/form/Input.js +97 -0
- package/dist/form/InputAction.d.ts +7 -0
- package/dist/form/InputAction.js +24 -0
- package/dist/form/Textarea.d.ts +5 -0
- package/dist/form/Textarea.js +23 -0
- package/dist/form/context.d.ts +12 -0
- package/dist/form/context.js +10 -0
- package/dist/form/controlProps.d.ts +23 -0
- package/dist/form/controlProps.js +20 -0
- package/dist/form/index.d.ts +7 -0
- package/dist/form/index.js +3 -0
- package/dist/form/types.d.ts +6 -0
- package/dist/form/types.js +1 -0
- package/dist/images/layers-2x.png +0 -0
- package/dist/images/layers.png +0 -0
- package/dist/images/marker-icon.png +0 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +22 -0
- package/dist/input-number/index.d.ts +16 -0
- package/dist/input-number/index.js +77 -0
- package/dist/internal/InputActionContext.d.ts +1 -0
- package/dist/internal/InputActionContext.js +3 -0
- package/dist/internal/cache.d.ts +14 -0
- package/dist/internal/cache.js +54 -0
- package/dist/internal/line.d.ts +4 -0
- package/dist/internal/line.js +21 -0
- package/dist/internal/paper.d.ts +1 -0
- package/dist/internal/paper.js +65 -0
- package/dist/internal/random.d.ts +3 -0
- package/dist/internal/random.js +30 -0
- package/dist/internal/recovery.d.ts +1 -0
- package/dist/internal/recovery.js +52 -0
- package/dist/internal/stroke.d.ts +24 -0
- package/dist/internal/stroke.js +144 -0
- package/dist/internal/surfaceRenderer.d.ts +33 -0
- package/dist/internal/surfaceRenderer.js +175 -0
- package/dist/internal/textQueue.d.ts +1 -0
- package/dist/internal/textQueue.js +37 -0
- package/dist/internal/textRenderer.d.ts +27 -0
- package/dist/internal/textRenderer.js +213 -0
- package/dist/internal/travelIcons.d.ts +24 -0
- package/dist/internal/travelIcons.js +14 -0
- package/dist/internal/useBrowserLayoutEffect.d.ts +2 -0
- package/dist/internal/useBrowserLayoutEffect.js +3 -0
- package/dist/internal/usePencilSurface.d.ts +3 -0
- package/dist/internal/usePencilSurface.js +108 -0
- package/dist/internal/useSelectionDrawing.d.ts +2 -0
- package/dist/internal/useSelectionDrawing.js +86 -0
- package/dist/internal/wash.d.ts +16 -0
- package/dist/internal/wash.js +149 -0
- package/dist/journey-map/MapScale.d.ts +4 -0
- package/dist/journey-map/MapScale.js +52 -0
- package/dist/journey-map/index.d.ts +39 -0
- package/dist/journey-map/index.js +195 -0
- package/dist/journey-map/terrain.d.ts +8 -0
- package/dist/journey-map/terrain.js +127 -0
- package/dist/overlay/Overlay.d.ts +65 -0
- package/dist/overlay/Overlay.js +77 -0
- package/dist/overlay/Popover.d.ts +43 -0
- package/dist/overlay/Popover.js +45 -0
- package/dist/overlay/index.d.ts +4 -0
- package/dist/overlay/index.js +2 -0
- package/dist/overlay/themeBridge.d.ts +8 -0
- package/dist/overlay/themeBridge.js +98 -0
- package/dist/pencil.d.ts +10 -0
- package/dist/pencil.js +39 -0
- package/dist/select/MultipleSelect.d.ts +44 -0
- package/dist/select/MultipleSelect.js +124 -0
- package/dist/select/SearchableSelect.d.ts +45 -0
- package/dist/select/SearchableSelect.js +50 -0
- package/dist/select/Select.d.ts +109 -0
- package/dist/select/Select.js +205 -0
- package/dist/select/index.d.ts +4 -0
- package/dist/select/index.js +2 -0
- package/dist/selection/Checkbox.d.ts +9 -0
- package/dist/selection/Checkbox.js +37 -0
- package/dist/selection/RadioGroup.d.ts +23 -0
- package/dist/selection/RadioGroup.js +82 -0
- package/dist/selection/Switch.d.ts +8 -0
- package/dist/selection/Switch.js +36 -0
- package/dist/selection/index.d.ts +6 -0
- package/dist/selection/index.js +3 -0
- package/dist/selection/useNativeChecked.d.ts +13 -0
- package/dist/selection/useNativeChecked.js +27 -0
- package/dist/slider/index.d.ts +11 -0
- package/dist/slider/index.js +45 -0
- package/dist/styles.css +3663 -0
- package/dist/tabs/index.d.ts +22 -0
- package/dist/tabs/index.js +42 -0
- package/dist/tokens.css +355 -0
- package/dist/tooltip/Tooltip.d.ts +24 -0
- package/dist/tooltip/Tooltip.js +32 -0
- package/dist/tooltip/index.d.ts +2 -0
- package/dist/tooltip/index.js +1 -0
- package/package.json +100 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Inkra contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,214 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Inkra
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Inkra is a pencil-styled React component library. It includes action, form, overlay, navigation, content and feedback components, plus Calendar, DayAgenda, JourneyMap and deterministic drawing primitives. The first `0.1.0` release is being prepared; this package is still an unpublished candidate unless a corresponding registry release has been announced.
|
|
4
|
+
|
|
5
|
+
Source and maintenance: [inkrajs/inkra](https://github.com/inkrajs/inkra).
|
|
6
|
+
|
|
7
|
+
Package name: `@inkra/react`. Import the scoped package and its stylesheet;
|
|
8
|
+
the unscoped `inkra` name is not this library's published package.
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
The package is prepared for npm-compatible installation, but this repository does not assume that a release has been published. In a workspace, depend on the local package according to the workspace package manager's conventions.
|
|
13
|
+
|
|
14
|
+
The manifest declares React 18 or newer as a peer dependency; release checks target React 18 and 19. ESM, TypeScript declarations, CSS and font assets are included. The release pipeline verifies SSR-to-browser hydration from the installed package, including form controls, portals, canvas recovery and the lazy-loaded map. Do not interpret the peer range as testing every future React version.
|
|
15
|
+
|
|
16
|
+
Inkra components require a React client boundary. Next.js and React Server Components are not a certified integration in 0.1.0; do not import interactive components directly into a Server Component. React 18 development SSR of Calendar still reports a layout-effect warning from react-day-picker 9; its browser hydration is checked separately. Applications requiring warning-free React 18 SSR should mount Calendar after hydration. Server and client must use matching locale, dates, values and theme inputs.
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
Import the component styles once near the application entry point:
|
|
21
|
+
|
|
22
|
+
```tsx
|
|
23
|
+
import '@inkra/react/styles.css';
|
|
24
|
+
|
|
25
|
+
import { Button, ButtonGroup, ButtonLink, PencilLine, PencilSurface, PencilText } from '@inkra/react';
|
|
26
|
+
|
|
27
|
+
export function Actions() {
|
|
28
|
+
return (
|
|
29
|
+
<>
|
|
30
|
+
<ButtonGroup aria-label="Document actions">
|
|
31
|
+
<Button variant="primary" size="md" seed="save-action">
|
|
32
|
+
Save changes
|
|
33
|
+
</Button>
|
|
34
|
+
<ButtonLink href="/preview" variant="outline">
|
|
35
|
+
Preview
|
|
36
|
+
</ButtonLink>
|
|
37
|
+
</ButtonGroup>
|
|
38
|
+
<div>
|
|
39
|
+
<PencilLine seed="section-divider" />
|
|
40
|
+
<PencilSurface variant="paper" seed="note-paper">
|
|
41
|
+
<PencilText seed="note-title">Project notes</PencilText>
|
|
42
|
+
</PencilSurface>
|
|
43
|
+
</div>
|
|
44
|
+
</>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
To use only the design tokens, import `@inkra/react/tokens.css` instead.
|
|
50
|
+
|
|
51
|
+
## Button
|
|
52
|
+
|
|
53
|
+
`Button` forwards its ref and native button attributes. Its default `type` is `button`, so placing it inside a form will not submit unexpectedly.
|
|
54
|
+
|
|
55
|
+
```tsx
|
|
56
|
+
<Button variant="secondary" size="sm" onClick={handleCancel}>
|
|
57
|
+
Cancel
|
|
58
|
+
</Button>
|
|
59
|
+
|
|
60
|
+
<Button loading seed="save-request">
|
|
61
|
+
Save
|
|
62
|
+
</Button>
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Supported Inkra props:
|
|
66
|
+
|
|
67
|
+
- `variant`: `primary`, `secondary`, `outline`, `ghost`, `destructive`, or `link`
|
|
68
|
+
- `size`: `xs`, `sm`, `md`, `lg`, `icon-xs`, `icon-sm`, `icon`, or `icon-lg`
|
|
69
|
+
- `loading`: marks the button busy and disables interaction
|
|
70
|
+
- `seed`: controls the deterministic hand-drawn decoration
|
|
71
|
+
- `startIcon` / `endIcon`: preserve logical icon placement in LTR and RTL layouts
|
|
72
|
+
|
|
73
|
+
All standard `button` props, including `disabled`, `name`, `value`, `form`, `aria-*`, and `data-*`, are passed to the native element.
|
|
74
|
+
|
|
75
|
+
`ButtonLink` renders a native anchor with the same visual props. Disabled or loading links remove their `href`, leave the tab order, expose `aria-disabled`, and block primary, modified, auxiliary and keyboard navigation. `ButtonGroup` renders `role="group"` with horizontal or vertical layout; provide `aria-label` or `aria-labelledby`. Icon-only controls use a square visual size and require an accessible name.
|
|
76
|
+
|
|
77
|
+
## Form Controls and Select
|
|
78
|
+
|
|
79
|
+
`Input` defaults to an underline appearance, with explicit `outline`, `soft` and `ghost` variants. It supports `startIcon`, `endIcon`, `prefix`, `suffix`, `clearable`, `loading`, `startAction`, `endAction`, `fullWidth` and logical `textAlign`. Use `onValueChange` for edits and clearing; native `onChange` does not receive fabricated clear events. `Field` connects labels, descriptions and errors.
|
|
80
|
+
|
|
81
|
+
`InputNumber` places decrease and increase buttons on either side of a centered numeric input, with no clear button. Keyboard deletion produces `null`; decimal stepping and out-of-range validation remain native. `Slider` supports single/range values, horizontal/vertical layout and `standard` or `inset` appearance.
|
|
82
|
+
|
|
83
|
+
`Select.Root` uses string values for single selection and string arrays with `multiple`. Multi-select remains open while toggling items and submits repeated values under the same field name. `Select.Clear` is a separate button; never nest it inside the trigger.
|
|
84
|
+
|
|
85
|
+
`Select.Trigger` supports `startIcon`, `endIcon`, `hideValue`, `hideIndicator`, `iconOnly`, `fullWidth` and `textAlign`. The existing `icon` prop replaces the dropdown indicator. Icon-only mode keeps a square hit target of at least 44px and retains selected text as an accessible description. Provide a Field/ARIA name and Tooltip for icon-only triggers. Decorative slots must not contain interactive controls.
|
|
86
|
+
|
|
87
|
+
`Select.Searchable` is a separate combobox API accepting `items` with `value`, `label`, optional `disabled` and `keywords`. `searchPlacement="trigger"` uses an editable input; `"popup"` places search inside the popup. It supports single/multiple values, filtering and clear controls. The compound Trigger appearance props do not implicitly apply to this separate API.
|
|
88
|
+
|
|
89
|
+
## Overlay Sections
|
|
90
|
+
|
|
91
|
+
`Overlay.Content layout="sections"` composes a fixed `Header`, a scrolling `Body`
|
|
92
|
+
and a fixed `Footer`. The default `layout="plain"` preserves the original padded
|
|
93
|
+
content layout. Keep the sections as direct children of Content.
|
|
94
|
+
|
|
95
|
+
```tsx
|
|
96
|
+
<Overlay.Root>
|
|
97
|
+
<Overlay.Trigger asChild><Button>Edit note</Button></Overlay.Trigger>
|
|
98
|
+
<Overlay.Portal>
|
|
99
|
+
<Overlay.Backdrop />
|
|
100
|
+
<Overlay.Content layout="sections">
|
|
101
|
+
<Overlay.Header closeLabel="Close">
|
|
102
|
+
<Overlay.Title>Edit note</Overlay.Title>
|
|
103
|
+
<Overlay.Description>Update the note title.</Overlay.Description>
|
|
104
|
+
</Overlay.Header>
|
|
105
|
+
<Overlay.Body>{/* Fields or other dialog content */}</Overlay.Body>
|
|
106
|
+
<Overlay.Footer>
|
|
107
|
+
<Overlay.Close asChild><Button variant="outline">Cancel</Button></Overlay.Close>
|
|
108
|
+
</Overlay.Footer>
|
|
109
|
+
</Overlay.Content>
|
|
110
|
+
</Overlay.Portal>
|
|
111
|
+
</Overlay.Root>
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Header includes a pencil close button by default (`showClose={false}` hides it).
|
|
115
|
+
Localize its accessible name and tooltip with `closeLabel`; `action` adds extra
|
|
116
|
+
header controls. Header/Footer use pencil separators by default; disable each
|
|
117
|
+
with `divided={false}`. Footer `align` is `start | center | end` (default end) and
|
|
118
|
+
wraps actions when needed. `Overlay.CloseButton label="Close"` is also available
|
|
119
|
+
for custom layouts. Native attributes, handlers and refs are forwarded.
|
|
120
|
+
|
|
121
|
+
Keep a form inside Body and link Footer submit buttons with matching `form`/`id`
|
|
122
|
+
attributes. This preserves validation and submission without wrapping the
|
|
123
|
+
sections in another scroll container. Radix continues to manage Escape,
|
|
124
|
+
outside interaction, modal focus trapping and focus return.
|
|
125
|
+
|
|
126
|
+
## Navigation And Feedback
|
|
127
|
+
|
|
128
|
+
`Tabs` exposes `Root`, `List`, `Trigger` and `Content`. It supports controlled or default values, horizontal/vertical orientation, RTL, automatic/manual activation and disabled triggers. `Content forceMount` preserves child state while hiding inactive panels. The selected pigment draws in and erases out, with reduced-motion fallbacks.
|
|
129
|
+
|
|
130
|
+
`Root.size` accepts `sm | md | lg` (default `md`), and `Root.animated={false}` disables pigment animation. `List.align` accepts `start | center | end`, `List.fullWidth` distributes triggers equally, and `List.loop={false}` stops keyboard wrapping. `Trigger.startIcon` and `Trigger.endIcon` accept decorative React nodes; provide an accessible name for icon-only triggers. Small tabs keep a minimum 44px hit target.
|
|
131
|
+
|
|
132
|
+
`List.divided` adds pencil separators between adjacent triggers (default false), following horizontal or vertical orientation without changing keyboard navigation.
|
|
133
|
+
|
|
134
|
+
`Tooltip` exposes `Provider`, `Root`, `Trigger`, `Portal` and `Content`. Use it for supplementary non-interactive text, never as the only accessible name or essential instructions. Portal content inherits the trigger's theme.
|
|
135
|
+
|
|
136
|
+
`Accordion` exposes `Root`, `Item`, `Header`, `Trigger` and `Content`. Use `type="single"` with a string value or `type="multiple"` with a string array. Single mode accepts `collapsible`; both support disabled items and keyboard navigation.
|
|
137
|
+
|
|
138
|
+
```tsx
|
|
139
|
+
<Tabs.Root defaultValue="notes">
|
|
140
|
+
<Tabs.List aria-label="Workspace">
|
|
141
|
+
<Tabs.Trigger value="notes">Notes</Tabs.Trigger>
|
|
142
|
+
<Tabs.Trigger value="drafts">Drafts</Tabs.Trigger>
|
|
143
|
+
</Tabs.List>
|
|
144
|
+
<Tabs.Content value="notes">Saved notes</Tabs.Content>
|
|
145
|
+
<Tabs.Content value="drafts">Unpublished drafts</Tabs.Content>
|
|
146
|
+
</Tabs.Root>
|
|
147
|
+
|
|
148
|
+
<Badge variant="success">Saved</Badge>
|
|
149
|
+
<Separator decorative />
|
|
150
|
+
<Skeleton style={{ width: 200, height: 20 }} />
|
|
151
|
+
<Progress label="Uploading" value={60} />
|
|
152
|
+
<Progress aria-label="Loading" value={null} />
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
`Badge` variants are `neutral`, `accent`, `success`, `warning`, `danger` and `info`. `Separator` has horizontal/vertical orientation and a decorative opt-out. `Skeleton` is a static, aria-hidden placeholder; mark its loading container `aria-busy`. `Progress` clamps numeric values to `0..max` (default 100); `null` is indeterminate without a fabricated percentage. Always provide a progress label.
|
|
156
|
+
|
|
157
|
+
`Badge.size` accepts `sm | md | lg` with optional `startIcon` and `endIcon`. `Separator.weight` clamps to 0.3–2 (default 0.9). `Skeleton.radius` uses the existing 0–8px pencil corner contract. `Progress.size` selects a 12/16/24px track (`sm/md/lg`); `dir`, `aria-valuetext`, refs and native DOM attributes remain available. Tooltip exposes the underlying delay, alignment, collision and hoverable-content controls alongside `Content.surfaceRadius`.
|
|
158
|
+
|
|
159
|
+
## Menus And Content
|
|
160
|
+
|
|
161
|
+
`DropdownMenu` exposes `Root`, `Trigger`, `Portal`, `Content`, `Item`, `CheckboxItem`, `RadioGroup`, `RadioItem`, `Group`, `Label` and `Separator`. It supports controlled open state, placement/collision props, disabled items, keyboard navigation and focus return. Use `Trigger asChild` with a Button; use `Item.destructive` for dangerous actions. Portal content inherits the trigger theme. Submenus are not included yet.
|
|
162
|
+
|
|
163
|
+
`Alert.Root` accepts `variant="info | success | warning | danger"`, an optional decorative `icon`, and native attributes. Compose with `Alert.Title` and `Alert.Description`. The default `role="status"` is polite; explicitly use `role="alert"` only for urgent feedback.
|
|
164
|
+
|
|
165
|
+
`Avatar.Root` provides fixed `sm/md/lg` sizes (32/44/64px), with `Avatar.Image` and `Avatar.Fallback`. Images require `alt`; name meaningful fallback content with `role="img"` and `aria-label`. Fallback supports `delayMs` and appears when the image cannot load.
|
|
166
|
+
|
|
167
|
+
`Card` exposes `Root`, `Header`, `Title`, `Description`, `Content` and `Footer`. Root accepts `variant="paper | quiet | outline"`, `radius` (0-8px) and `seed`; Title accepts `as="h2 | h3 | h4 | h5 | h6"` (default h3). Native props and refs remain available.
|
|
168
|
+
|
|
169
|
+
`Table` exposes `Container`, `Root`, `Header`, `Body`, `Footer`, `Row`, `Head`, `Cell` and `Caption`, preserving native table semantics. Root accepts `density="compact | comfortable"`; `Row.selected` is visual emphasis only. Give the scrollable Container an accessible name and use a Caption and appropriate Head scope. Sorting, filtering, pagination and grid selection are not built in.
|
|
170
|
+
|
|
171
|
+
Content layout options preserve existing defaults:
|
|
172
|
+
|
|
173
|
+
- `Card.Root.size` and `Alert.Root.size` accept `sm | md | lg` for 12/16/24px padding (default md), without reducing text size.
|
|
174
|
+
- `Card.Root.divided` defaults to true; `Header.divided` and `Footer.divided` override it locally. `Header.action` accepts an independent action node. `Content.padding="none"` removes content padding for edge-to-edge content. `Footer.justify` accepts `start | center | end | between`, respecting text direction.
|
|
175
|
+
- `Alert.Root.appearance` accepts `soft | outline` (default soft). `actions` places actual controls after the message; it does not add automatic dismissal or focus changes.
|
|
176
|
+
- `Avatar.Root.radius` clamps to 0-8px, including pencil and image corners; `bordered={false}` removes the outline. `Avatar.Image.fit` accepts `cover | contain` (default cover).
|
|
177
|
+
- `Table.Root.striped`, `hoverable` and `stickyHeader` default to false. Constrain `Table.Container` with `style={{ maxHeight: 240 }}` for sticky scrolling. `captionSide` accepts `top | bottom`. `Head.align` and `Cell.align` accept logical `start | center | end`, retaining native alignment values for compatibility. Hover feedback does not imply row actions.
|
|
178
|
+
|
|
179
|
+
## Travel Components
|
|
180
|
+
|
|
181
|
+
`Calendar` wraps React DayPicker with default `appearance="itinerary"` day cards and optional `appearance="picker"`. It retains single/multiple/range selection, month control, disabled matchers, locale and keyboard navigation. Supply `selected` and `onSelect` for controlled selection. Events have independent `onEventSelect` handling; `displayRange` and `renderDayAccessory` customize the itinerary. Narrow itinerary grids retain seven columns and hide event text while preserving accessible names; picker targets remain at least 44px.
|
|
182
|
+
|
|
183
|
+
`DayAgenda` takes a local `date` (`YYYY-MM-DD`) and `AgendaEvent[]` with `id`, `title`, optional `description`, `startMinute` and `endMinute`. Minutes are relative to that day's midnight. Cross-day intervals show continuation; missing times remain pending and missing ends remain points. Its vertical timeline uses a piecewise scale for readable short events and separate lanes for overlaps. `selectedEvent`, `onEventSelect`, `onPreviousDay` and `onNextDay` provide interaction. Supply localized labels, `locale` and optional `timeZoneLabel`; no time zones or flight durations are inferred.
|
|
184
|
+
|
|
185
|
+
`JourneyMap` accepts `places`, optional GeoJSON `geography`, `routes`, `selectedPlace`, `onPlaceSelect` and required `attribution`. Place/route coordinates use latitude then longitude; GeoJSON retains longitude then latitude. Leaflet is loaded only in the browser. The map supports pan, zoom and reset, with an equivalent place-button list. It does not request location permissions, fetch map tiles, calculate routes or infer travel times. Demo geography is illustrative, not navigation data. Use `labels` to localize controls and failure feedback, and import `@inkra/react/styles.css` for all required map styles.
|
|
186
|
+
|
|
187
|
+
## Pencil Primitives
|
|
188
|
+
|
|
189
|
+
`PencilSurface` renders pencil material behind semantic DOM content. Available variants are `paper`, `action`, `quiet`, `badge`, `outline`, `danger`, `ghost`, `selection`, `wash`, and `full`. Use `selection` for the transparent selected-tab wash; it intentionally has no paper fill, outline, or bleed.
|
|
190
|
+
|
|
191
|
+
`PencilText` keeps its string in the DOM for selection, copy, search, and assistive technology. Browser enhancement paints the same glyph geometry with the traced C lettering preset; unavailable canvas or font loading leaves the readable DOM fallback visible.
|
|
192
|
+
|
|
193
|
+
`PencilIcon` accepts familiar SVG path data and deposits pigment along sampled geometry. See `docs/pencil-contract.md` in the workspace for the current alpha contract.
|
|
194
|
+
|
|
195
|
+
`PencilLine` is an aria-hidden canvas decoration using the same pressure, grain, breaks, and repeated-pass renderer as surfaces and icons. It defaults to horizontal and supports a native vertical stroke without rotating a horizontal bitmap:
|
|
196
|
+
|
|
197
|
+
```tsx
|
|
198
|
+
<PencilLine seed="notes-divider" className="notes-divider" />
|
|
199
|
+
<PencilLine orientation="vertical" seed="sidebar-divider" className="sidebar-divider" />
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## Font license
|
|
203
|
+
|
|
204
|
+
The package includes `Trip Map Hand`, a modified web subset of Yozai Light v0.868, under the SIL Open Font License 1.1. The font is not covered by Inkra's MIT software license. See `THIRD_PARTY_NOTICES.md` and `Yozai-OFL.txt` in the package.
|
|
205
|
+
|
|
206
|
+
## Development
|
|
207
|
+
|
|
208
|
+
```sh
|
|
209
|
+
npm run typecheck
|
|
210
|
+
npm test
|
|
211
|
+
npm run pack:check
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
`npm test` builds the package before running the SSR and determinism tests. `pack:check` prints the files that would be included without publishing anything.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Third-Party Notices
|
|
2
|
+
|
|
3
|
+
## Trip Map Hand font subset
|
|
4
|
+
|
|
5
|
+
`dist/assets/ui-hand-yozai.woff2` is a web subset of Yozai Light v0.868 by LXGW, derived from work by Y.Oz. The subset uses the modified family name `Trip Map Hand` and is included to provide the handwriting geometry used by Inkra's pencil-text renderer.
|
|
6
|
+
|
|
7
|
+
The font software is licensed under the SIL Open Font License 1.1. The complete license and copyright notice are included in `Yozai-OFL.txt`. The font is not covered by Inkra's MIT software license.
|
|
8
|
+
|
|
9
|
+
Source: Yozai Font release v0.868.
|
|
10
|
+
|
|
11
|
+
## Leaflet
|
|
12
|
+
|
|
13
|
+
The distributed stylesheet includes Leaflet CSS and supporting image assets.
|
|
14
|
+
|
|
15
|
+
BSD 2-Clause License
|
|
16
|
+
|
|
17
|
+
Copyright (c) 2010-2023, Volodymyr Agafonkin
|
|
18
|
+
Copyright (c) 2010-2011, CloudMade
|
|
19
|
+
All rights reserved.
|
|
20
|
+
|
|
21
|
+
Redistribution and use in source and binary forms, with or without
|
|
22
|
+
modification, are permitted provided that the following conditions are met:
|
|
23
|
+
|
|
24
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
25
|
+
list of conditions and the following disclaimer.
|
|
26
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
27
|
+
this list of conditions and the following disclaimer in the documentation
|
|
28
|
+
and/or other materials provided with the distribution.
|
|
29
|
+
|
|
30
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
31
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
32
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
33
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
34
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
35
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
36
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
37
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
38
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
39
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
package/Yozai-OFL.txt
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
Copyright 2020, 2024 LXGW (https://github.com/lxgw/yozai-font)
|
|
2
|
+
Copyright (c) 2021-03-07, Y.Oz (Y.OzVox) (http://yozvox.web.fc2.com), words containing "Y.Oz" or "YOz" are reserved as font names.
|
|
3
|
+
|
|
4
|
+
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
|
5
|
+
This license is copied below, and is also available with a FAQ at:
|
|
6
|
+
http://scripts.sil.org/OFL
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
-----------------------------------------------------------
|
|
10
|
+
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
|
11
|
+
-----------------------------------------------------------
|
|
12
|
+
|
|
13
|
+
PREAMBLE
|
|
14
|
+
The goals of the Open Font License (OFL) are to stimulate worldwide
|
|
15
|
+
development of collaborative font projects, to support the font creation
|
|
16
|
+
efforts of academic and linguistic communities, and to provide a free and
|
|
17
|
+
open framework in which fonts may be shared and improved in partnership
|
|
18
|
+
with others.
|
|
19
|
+
|
|
20
|
+
The OFL allows the licensed fonts to be used, studied, modified and
|
|
21
|
+
redistributed freely as long as they are not sold by themselves. The
|
|
22
|
+
fonts, including any derivative works, can be bundled, embedded,
|
|
23
|
+
redistributed and/or sold with any software provided that any reserved
|
|
24
|
+
names are not used by derivative works. The fonts and derivatives,
|
|
25
|
+
however, cannot be released under any other type of license. The
|
|
26
|
+
requirement for fonts to remain under this license does not apply
|
|
27
|
+
to any document created using the fonts or their derivatives.
|
|
28
|
+
|
|
29
|
+
DEFINITIONS
|
|
30
|
+
"Font Software" refers to the set of files released by the Copyright
|
|
31
|
+
Holder(s) under this license and clearly marked as such. This may
|
|
32
|
+
include source files, build scripts and documentation.
|
|
33
|
+
|
|
34
|
+
"Reserved Font Name" refers to any names specified as such after the
|
|
35
|
+
copyright statement(s).
|
|
36
|
+
|
|
37
|
+
"Original Version" refers to the collection of Font Software components as
|
|
38
|
+
distributed by the Copyright Holder(s).
|
|
39
|
+
|
|
40
|
+
"Modified Version" refers to any derivative made by adding to, deleting,
|
|
41
|
+
or substituting -- in part or in whole -- any of the components of the
|
|
42
|
+
Original Version, by changing formats or by porting the Font Software to a
|
|
43
|
+
new environment.
|
|
44
|
+
|
|
45
|
+
"Author" refers to any designer, engineer, programmer, technical
|
|
46
|
+
writer or other person who contributed to the Font Software.
|
|
47
|
+
|
|
48
|
+
PERMISSION & CONDITIONS
|
|
49
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
50
|
+
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
|
51
|
+
redistribute, and sell modified and unmodified copies of the Font
|
|
52
|
+
Software, subject to the following conditions:
|
|
53
|
+
|
|
54
|
+
1) Neither the Font Software nor any of its individual components,
|
|
55
|
+
in Original or Modified Versions, may be sold by itself.
|
|
56
|
+
|
|
57
|
+
2) Original or Modified Versions of the Font Software may be bundled,
|
|
58
|
+
redistributed and/or sold with any software, provided that each copy
|
|
59
|
+
contains the above copyright notice and this license. These can be
|
|
60
|
+
included either as stand-alone text files, human-readable headers or
|
|
61
|
+
in the appropriate machine-readable metadata fields within text or
|
|
62
|
+
binary files as long as those fields can be easily viewed by the user.
|
|
63
|
+
|
|
64
|
+
3) No Modified Version of the Font Software may use the Reserved Font
|
|
65
|
+
Name(s) unless explicit written permission is granted by the corresponding
|
|
66
|
+
Copyright Holder. This restriction only applies to the primary font name as
|
|
67
|
+
presented to the users.
|
|
68
|
+
|
|
69
|
+
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
|
70
|
+
Software shall not be used to promote, endorse or advertise any
|
|
71
|
+
Modified Version, except to acknowledge the contribution(s) of the
|
|
72
|
+
Copyright Holder(s) and the Author(s) or with their explicit written
|
|
73
|
+
permission.
|
|
74
|
+
|
|
75
|
+
5) The Font Software, modified or unmodified, in part or in whole,
|
|
76
|
+
must be distributed entirely under this license, and must not be
|
|
77
|
+
distributed under any other license. The requirement for fonts to
|
|
78
|
+
remain under this license does not apply to any document created
|
|
79
|
+
using the Font Software.
|
|
80
|
+
|
|
81
|
+
TERMINATION
|
|
82
|
+
This license becomes null and void if any of the above conditions are
|
|
83
|
+
not met.
|
|
84
|
+
|
|
85
|
+
DISCLAIMER
|
|
86
|
+
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
87
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
|
88
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
|
89
|
+
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
|
90
|
+
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
91
|
+
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
|
92
|
+
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
93
|
+
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
|
94
|
+
OTHER DEALINGS IN THE FONT SOFTWARE.
|
package/dist/Button.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { AnchorHTMLAttributes, ButtonHTMLAttributes, HTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
export type ButtonVariant = 'primary' | 'secondary' | 'outline' | 'ghost' | 'destructive' | 'link';
|
|
3
|
+
export type ButtonSize = 'xs' | 'sm' | 'md' | 'lg' | 'icon-xs' | 'icon-sm' | 'icon' | 'icon-lg';
|
|
4
|
+
export type ButtonGroupOrientation = 'horizontal' | 'vertical';
|
|
5
|
+
export type ButtonAlign = 'start' | 'center' | 'end';
|
|
6
|
+
export type ButtonLoadingPosition = 'start' | 'center' | 'end';
|
|
7
|
+
interface SharedButtonProps {
|
|
8
|
+
variant?: ButtonVariant;
|
|
9
|
+
size?: ButtonSize;
|
|
10
|
+
loading?: boolean;
|
|
11
|
+
seed?: string | number;
|
|
12
|
+
startIcon?: ReactNode;
|
|
13
|
+
endIcon?: ReactNode;
|
|
14
|
+
fullWidth?: boolean;
|
|
15
|
+
align?: ButtonAlign;
|
|
16
|
+
loadingPosition?: ButtonLoadingPosition;
|
|
17
|
+
loadingIndicator?: ReactNode;
|
|
18
|
+
}
|
|
19
|
+
export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement>, SharedButtonProps {
|
|
20
|
+
}
|
|
21
|
+
export interface ButtonLinkProps extends Omit<AnchorHTMLAttributes<HTMLAnchorElement>, 'children'>, SharedButtonProps {
|
|
22
|
+
children?: ReactNode;
|
|
23
|
+
disabled?: boolean;
|
|
24
|
+
}
|
|
25
|
+
export interface ButtonGroupProps extends HTMLAttributes<HTMLDivElement> {
|
|
26
|
+
orientation?: ButtonGroupOrientation;
|
|
27
|
+
size?: ButtonSize;
|
|
28
|
+
variant?: ButtonVariant;
|
|
29
|
+
disabled?: boolean;
|
|
30
|
+
fullWidth?: boolean;
|
|
31
|
+
equalWidth?: boolean;
|
|
32
|
+
}
|
|
33
|
+
export declare const Button: import("react").ForwardRefExoticComponent<ButtonProps & import("react").RefAttributes<HTMLButtonElement>>;
|
|
34
|
+
export declare const ButtonLink: import("react").ForwardRefExoticComponent<ButtonLinkProps & import("react").RefAttributes<HTMLAnchorElement>>;
|
|
35
|
+
export declare const ButtonGroup: import("react").ForwardRefExoticComponent<ButtonGroupProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
36
|
+
export {};
|
package/dist/Button.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { createContext, forwardRef, useContext, useId } from 'react';
|
|
3
|
+
import { PencilSurface } from './PencilSurface.js';
|
|
4
|
+
import { PencilText } from './PencilText.js';
|
|
5
|
+
import { PencilLine } from './PencilLine.js';
|
|
6
|
+
import { InputActionContext } from './internal/InputActionContext.js';
|
|
7
|
+
const ButtonGroupContext = createContext(null);
|
|
8
|
+
function surfaceVariant(variant) {
|
|
9
|
+
if (variant === 'primary')
|
|
10
|
+
return 'action';
|
|
11
|
+
if (variant === 'secondary' || variant === 'ghost')
|
|
12
|
+
return 'quiet';
|
|
13
|
+
if (variant === 'outline')
|
|
14
|
+
return 'outline';
|
|
15
|
+
if (variant === 'destructive')
|
|
16
|
+
return 'danger';
|
|
17
|
+
return 'ghost';
|
|
18
|
+
}
|
|
19
|
+
function classNames(className) {
|
|
20
|
+
return ['inkra-button', className].filter(Boolean).join(' ');
|
|
21
|
+
}
|
|
22
|
+
function accessibleLabel(ariaLabel, loading, children) {
|
|
23
|
+
return ariaLabel ?? (loading && typeof children === 'string' ? children : undefined);
|
|
24
|
+
}
|
|
25
|
+
function ButtonVisual({ children, endIcon, loading, loadingPosition, loadingIndicator, seed, startIcon, variant }) {
|
|
26
|
+
const group = useContext(ButtonGroupContext);
|
|
27
|
+
const inputAction = useContext(InputActionContext);
|
|
28
|
+
const sharedOutline = group !== null || inputAction;
|
|
29
|
+
const indicator = _jsx("span", { "aria-hidden": "true", className: "inkra-button__loading-indicator", children: loadingIndicator ?? _jsx("span", { className: "inkra-button__spinner" }) });
|
|
30
|
+
const iconSlot = (side, icon) => {
|
|
31
|
+
const reserved = loadingPosition === side;
|
|
32
|
+
if (icon == null && !reserved)
|
|
33
|
+
return null;
|
|
34
|
+
return _jsxs("span", { "aria-hidden": "true", className: `inkra-button__icon inkra-button__icon--${side}`, "data-loading-slot": reserved || undefined, children: [_jsx("span", { className: "inkra-button__icon-content", children: icon }), reserved && loading ? indicator : null] });
|
|
35
|
+
};
|
|
36
|
+
const label = typeof children === 'string'
|
|
37
|
+
? _jsx(PencilText, { seed: `${seed}-label`, children: children })
|
|
38
|
+
: children == null ? null : _jsx("span", { children: children });
|
|
39
|
+
return (_jsxs(_Fragment, { children: [_jsx(PencilSurface, { as: "span", className: "inkra-button__surface", clipContent: sharedOutline, radius: sharedOutline ? 0 : undefined, seed: seed, variant: inputAction ? 'ghost' : surfaceVariant(variant), children: _jsxs("span", { className: "inkra-button__content", children: [loading && loadingPosition === 'center' ? indicator : null, iconSlot('start', startIcon), label == null ? null : _jsxs("span", { className: "inkra-button__label", children: [label, variant === 'link' ? _jsx(PencilLine, { className: "inkra-button__underline", seed: `${seed}-underline`, weight: 0.9 }) : null] }), iconSlot('end', endIcon)] }) }), _jsx(PencilSurface, { as: "span", "aria-hidden": "true", className: "inkra-button__focus-ring", variant: "outline", seed: `${seed}-focus` }), group === null ? null : _jsx(PencilLine, { className: "inkra-button-group__divider", orientation: group.orientation === 'horizontal' ? 'vertical' : 'horizontal', seed: `${seed}-group-divider` })] }));
|
|
40
|
+
}
|
|
41
|
+
export const Button = forwardRef(function Button({ children, 'aria-label': ariaLabel, className, disabled = false, endIcon, loading = false, loadingPosition = 'center', loadingIndicator, fullWidth = false, align = 'center', seed, size: sizeProp, startIcon, type = 'button', variant: variantProp, ...props }, ref) {
|
|
42
|
+
const id = useId();
|
|
43
|
+
const group = useContext(ButtonGroupContext);
|
|
44
|
+
const size = sizeProp ?? group?.size ?? 'md';
|
|
45
|
+
const variant = variantProp ?? group?.variant ?? 'primary';
|
|
46
|
+
const position = size.startsWith('icon') ? 'center' : loadingPosition;
|
|
47
|
+
const resolvedSeed = seed ?? `inkra-button-${id}`;
|
|
48
|
+
return (_jsx("button", { ...props, "aria-label": accessibleLabel(ariaLabel, loading, children), "aria-busy": loading || undefined, className: classNames(className), "data-loading": loading || undefined, "data-loading-position": position, "data-full-width": fullWidth && !size.startsWith('icon') || undefined, "data-align": align, "data-size": size, "data-variant": variant, disabled: disabled || loading || group?.disabled, ref: ref, type: type, children: _jsx(ButtonVisual, { endIcon: endIcon, loading: loading, loadingPosition: position, loadingIndicator: loadingIndicator, seed: resolvedSeed, startIcon: startIcon, variant: variant, children: children }) }));
|
|
49
|
+
});
|
|
50
|
+
export const ButtonLink = forwardRef(function ButtonLink({ children, 'aria-label': ariaLabel, className, disabled = false, endIcon, href, loading = false, loadingPosition = 'center', loadingIndicator, fullWidth = false, align = 'center', onAuxClick, onClick, onKeyDown, seed, size: sizeProp, startIcon, tabIndex, variant: variantProp, ...props }, ref) {
|
|
51
|
+
const id = useId();
|
|
52
|
+
const group = useContext(ButtonGroupContext);
|
|
53
|
+
const size = sizeProp ?? group?.size ?? 'md';
|
|
54
|
+
const variant = variantProp ?? group?.variant ?? 'primary';
|
|
55
|
+
const position = size.startsWith('icon') ? 'center' : loadingPosition;
|
|
56
|
+
const resolvedSeed = seed ?? `inkra-button-link-${id}`;
|
|
57
|
+
const interactionDisabled = disabled || loading || group?.disabled;
|
|
58
|
+
const handleClick = (event) => {
|
|
59
|
+
if (interactionDisabled) {
|
|
60
|
+
event.preventDefault();
|
|
61
|
+
event.stopPropagation();
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
onClick?.(event);
|
|
65
|
+
};
|
|
66
|
+
const handleAuxClick = (event) => {
|
|
67
|
+
if (interactionDisabled) {
|
|
68
|
+
event.preventDefault();
|
|
69
|
+
event.stopPropagation();
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
onAuxClick?.(event);
|
|
73
|
+
};
|
|
74
|
+
const handleKeyDown = (event) => {
|
|
75
|
+
if (interactionDisabled) {
|
|
76
|
+
if (event.key === 'Enter' || event.key === ' ')
|
|
77
|
+
event.preventDefault();
|
|
78
|
+
event.stopPropagation();
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
onKeyDown?.(event);
|
|
82
|
+
};
|
|
83
|
+
return (_jsx("a", { ...props, "aria-label": accessibleLabel(ariaLabel, loading, children), "aria-busy": loading || undefined, "aria-disabled": interactionDisabled || undefined, className: classNames(className), "data-disabled": interactionDisabled || undefined, "data-loading": loading || undefined, "data-loading-position": position, "data-full-width": fullWidth && !size.startsWith('icon') || undefined, "data-align": align, "data-size": size, "data-variant": variant, href: interactionDisabled ? undefined : href, onAuxClick: handleAuxClick, onClick: handleClick, onKeyDown: handleKeyDown, ref: ref, tabIndex: interactionDisabled ? -1 : tabIndex, children: _jsx(ButtonVisual, { endIcon: endIcon, loading: loading, loadingPosition: position, loadingIndicator: loadingIndicator, seed: resolvedSeed, startIcon: startIcon, variant: variant, children: children }) }));
|
|
84
|
+
});
|
|
85
|
+
export const ButtonGroup = forwardRef(function ButtonGroup({ children, className, orientation = 'horizontal', size, variant, disabled = false, fullWidth = false, equalWidth = false, ...props }, ref) {
|
|
86
|
+
const classes = ['inkra-button-group', className].filter(Boolean).join(' ');
|
|
87
|
+
const id = useId();
|
|
88
|
+
return (_jsx(ButtonGroupContext.Provider, { value: { orientation, size, variant, disabled }, children: _jsx(PencilSurface, { ...props, className: classes, "data-orientation": orientation, "data-full-width": fullWidth || undefined, "data-equal-width": equalWidth || undefined, "aria-disabled": disabled || undefined, radius: 8, ref: ref, role: "group", seed: `inkra-button-group-${id}`, variant: "outline", children: children }) }));
|
|
89
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { CanvasHTMLAttributes } from 'react';
|
|
2
|
+
export interface PencilIconPath {
|
|
3
|
+
d: string;
|
|
4
|
+
mode?: 'stroke' | 'wash' | 'scuff';
|
|
5
|
+
}
|
|
6
|
+
export interface PencilIconBadge {
|
|
7
|
+
paths: readonly PencilIconPath[];
|
|
8
|
+
sourceSize?: number;
|
|
9
|
+
position?: 'top-start' | 'top-end' | 'bottom-start' | 'bottom-end';
|
|
10
|
+
/** Relative canvas size, clamped to 0.35-0.65. Defaults to 0.55. */
|
|
11
|
+
scale?: number;
|
|
12
|
+
}
|
|
13
|
+
export interface PencilIconProps extends Omit<CanvasHTMLAttributes<HTMLCanvasElement>, 'children' | 'height' | 'width'> {
|
|
14
|
+
paths: readonly PencilIconPath[];
|
|
15
|
+
badge?: PencilIconBadge;
|
|
16
|
+
seed?: string | number;
|
|
17
|
+
size?: number;
|
|
18
|
+
sourceSize?: number;
|
|
19
|
+
active?: boolean;
|
|
20
|
+
decorative?: boolean;
|
|
21
|
+
}
|
|
22
|
+
export declare const PencilIcon: import("react").ForwardRefExoticComponent<PencilIconProps & import("react").RefAttributes<HTMLCanvasElement>>;
|