cattle-care-ui 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/README.md +98 -0
- package/dist/components/Button.d.ts +14 -0
- package/dist/components/Card.d.ts +18 -0
- package/dist/components/Checkbox.d.ts +9 -0
- package/dist/components/FilterSection.d.ts +11 -0
- package/dist/components/HighlightText.d.ts +4 -0
- package/dist/components/Menu.d.ts +7 -0
- package/dist/components/MenuItem.d.ts +10 -0
- package/dist/components/RadioButton.d.ts +11 -0
- package/dist/components/Tabs.d.ts +17 -0
- package/dist/components/Tag.d.ts +8 -0
- package/dist/components/TextField.d.ts +11 -0
- package/dist/components/Toolbar.d.ts +14 -0
- package/dist/components/UiElementsSidebar.d.ts +9 -0
- package/dist/index.css +2 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +580 -0
- package/dist/index.js.map +1 -0
- package/dist/utils/format.d.ts +3 -0
- package/package.json +64 -0
package/README.md
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# cattle-care-ui
|
|
2
|
+
|
|
3
|
+
Shared, presentational React components extracted from [cc-workers-schedule](../cc-workers-schedule), for reuse across other Cattle Care projects (e.g. `cattle-care`, `cc-farmer-ui`).
|
|
4
|
+
|
|
5
|
+
## What's here
|
|
6
|
+
|
|
7
|
+
- `src/components/` — presentational components (props in, JSX out, CSS Modules). No app state, no data-layer imports.
|
|
8
|
+
- `src/styles/tokens.css` — shared color tokens (CSS custom properties: brand, text, surfaces, borders, status).
|
|
9
|
+
- `src/styles/fonts.css` — shared typography tokens (CSS custom properties: font family, size, weight, line height).
|
|
10
|
+
- `src/styles/typography.css` — composable text-style utility classes (`.text-base`, `.text-bold`, `.text-sm`, `.text-lg`, `.text-2-line`) built on the font tokens.
|
|
11
|
+
- `src/utils/format.ts` — small formatting helpers.
|
|
12
|
+
- `src/index.ts` — the package's public entry point (barrel export).
|
|
13
|
+
|
|
14
|
+
Components are typed and documented via Storybook stories (`*.stories.tsx`) colocated next to each component.
|
|
15
|
+
|
|
16
|
+
### Font
|
|
17
|
+
|
|
18
|
+
Components assume the **Inter** font is loaded by the consuming app. Load the variable weight range (not a discrete list) so any `font-weight` value — including in-between ones like `450` — renders correctly instead of snapping to the nearest loaded static weight:
|
|
19
|
+
|
|
20
|
+
```html
|
|
21
|
+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@100..900&display=swap" rel="stylesheet" />
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
It is not bundled with this package.
|
|
25
|
+
|
|
26
|
+
## Development
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npm install
|
|
30
|
+
npm run storybook # dev server at http://localhost:6006
|
|
31
|
+
npm run build-storybook # static build to storybook-static/
|
|
32
|
+
npm run typecheck
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Visual review (Chromatic)
|
|
36
|
+
|
|
37
|
+
This repo has the `@chromatic-com/storybook` addon and a `chromatic` script wired up. To connect it to a project:
|
|
38
|
+
|
|
39
|
+
1. Sign up / log in at [chromatic.com](https://www.chromatic.com/) with this GitHub repo.
|
|
40
|
+
2. Copy the generated **project token**.
|
|
41
|
+
3. Run locally: `CHROMATIC_PROJECT_TOKEN=<token> npm run chromatic`
|
|
42
|
+
— or add it as a `CHROMATIC_PROJECT_TOKEN` secret in GitHub Actions for CI-based publishing on every push.
|
|
43
|
+
|
|
44
|
+
## Adding a component
|
|
45
|
+
|
|
46
|
+
1. Move the component + its `.module.css` into `src/components/`, with app-specific state/context replaced by props/callbacks.
|
|
47
|
+
2. Add a `<Component>.stories.tsx` next to it.
|
|
48
|
+
3. Export it from `src/index.ts`.
|
|
49
|
+
4. Run `npm run typecheck` and `npm run build-storybook` to verify.
|
|
50
|
+
|
|
51
|
+
## Consuming from another project
|
|
52
|
+
|
|
53
|
+
This package is published to the public npm registry.
|
|
54
|
+
|
|
55
|
+
```sh
|
|
56
|
+
npm install cattle-care-ui react react-dom
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
`react` and `react-dom` are peer dependencies — install matching versions (React 19) in your app if not already present.
|
|
60
|
+
|
|
61
|
+
Import the compiled stylesheet once (e.g. in your app's root entry file) and import components as named exports — no CSS Modules bundler configuration is required on the consuming side, everything is pre-compiled into a single stylesheet:
|
|
62
|
+
|
|
63
|
+
```tsx
|
|
64
|
+
import 'cattle-care-ui/style.css';
|
|
65
|
+
import { Button, Tabs } from 'cattle-care-ui';
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
> If your app already defines global CSS custom properties with the same names as this library's design tokens (e.g. `--text-primary`, `--border`), import order matters: whichever stylesheet is imported last wins for those variable names. This library doesn't namespace its tokens.
|
|
69
|
+
|
|
70
|
+
### Publishing a new version
|
|
71
|
+
|
|
72
|
+
Releases are published automatically by `.github/workflows/publish.yml` when a GitHub Release is published (requires an `NPM_TOKEN` repo secret with npm publish access, added under Settings → Secrets and variables → Actions). To cut a release: bump `version` in `package.json`, commit, then draft a new GitHub Release with a matching tag.
|
|
73
|
+
|
|
74
|
+
To build the package locally without publishing: `npm run build` (outputs to `dist/`).
|
|
75
|
+
|
|
76
|
+
## Components currently included
|
|
77
|
+
|
|
78
|
+
| Component | Notes |
|
|
79
|
+
|---|---|
|
|
80
|
+
| `Button` | `primary`/`secondary`/`tertiary` variants with ripple-fill hover (originally from `ConfirmDialog`'s `.btn-primary`/`.btn-secondary` global classes), `sm`/`base`/`lg` sizes, disabled state |
|
|
81
|
+
| `Card` | Visual shell only (surface, radius, hover ring, `completed`/`stacked`/`interactive`/`dragging` states), generalized from `ShiftCard`. Drag-and-drop and content stay with the consumer. |
|
|
82
|
+
| `Tag` | Generalizes the repeated tag/pill/badge pattern found in `ShiftCard`, `WorkerRow`, `BpoRow`, `BacklogSidebar`, `VideoPanel`, `AppHeader`, `FiltersMenu`. Variants: `neutral`, `pill`, `accent`, `success`, `danger`, `count`. |
|
|
83
|
+
| `Toolbar` | Visual shell only (floating search bar, keyboard-shortcut badge, `children` slot for filter/sort controls), generalized from `Toolbar`. The original's `FiltersBar` content and absolute page positioning stay with the consumer — this only ships the search input + layout shell. |
|
|
84
|
+
| `Checkbox` | Custom animated checkbox |
|
|
85
|
+
| `HighlightText` | Wraps matching substrings in `<mark>` |
|
|
86
|
+
| `FilterSection` | Generic labeled option list with optional search + select-all |
|
|
87
|
+
| `UiElementsSidebar` | Static nav sidebar for a component catalog page |
|
|
88
|
+
| icons (`ChevronLeftIcon`, etc.) | Inline SVG icon set |
|
|
89
|
+
|
|
90
|
+
More components from the source app (`Board`, full `ShiftCard` composition, `VideoPanel`, etc.) are coupled to app-specific state/data and haven't been extracted yet — they'd need a props/callback-driven refactor first.
|
|
91
|
+
|
|
92
|
+
### Notes on token cleanup
|
|
93
|
+
|
|
94
|
+
While extracting `Tag`, two untokenized colors from the source app were reconciled:
|
|
95
|
+
- `#e3f6ea` / `#2f8a52` (success bg/text, used for "completed"/"time spent" states) → added as `--success-bg` (paired with the existing `--success-text`).
|
|
96
|
+
- `#fbe2e2` / `#b23a3a` (a second, undocumented "danger" pair used for the idle-worker stat) → consolidated into the existing `--danger-bg`/`--danger-text` tokens rather than kept as a duplicate. If the source app's visual distinction between these two reds was intentional, flag it before porting `Tag`'s danger variant back.
|
|
97
|
+
|
|
98
|
+
`Button`'s primary variant originally used `--accent` (`#0090d9`) as its idle background with white text — only ~3.5:1 contrast, failing WCAG AA for normal text (4.5:1 required). Its idle background now uses the darker `--accent-hover` (`#007ebd`, ~4.6:1, passes AA); the hover/press ripple fill uses translucent white/black (`rgba(255,255,255,0.08)` / `rgba(0,0,0,0.08)`) instead of a solid color.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ButtonHTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
type ButtonVariant = 'primary' | 'secondary' | 'tertiary' | 'dangerous';
|
|
3
|
+
type ButtonSize = 'sm' | 'base' | 'lg';
|
|
4
|
+
interface ButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'className'> {
|
|
5
|
+
variant?: ButtonVariant;
|
|
6
|
+
size?: ButtonSize;
|
|
7
|
+
/** Icon shown before the label. Omit `children` to render an icon-only square button — pass `aria-label` in that case. */
|
|
8
|
+
leadingIcon?: ReactNode;
|
|
9
|
+
/** Icon shown after the label. */
|
|
10
|
+
trailingIcon?: ReactNode;
|
|
11
|
+
children?: ReactNode;
|
|
12
|
+
}
|
|
13
|
+
export declare function Button({ variant, size, leadingIcon, trailingIcon, children, ...rest }: ButtonProps): import("react").JSX.Element;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { HTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
interface CardProps extends Omit<HTMLAttributes<HTMLDivElement>, 'className'> {
|
|
3
|
+
/** Shows a second sheet behind the card, for representing a stack/batch. */
|
|
4
|
+
stacked?: boolean;
|
|
5
|
+
/** Success-tinted surface, e.g. a completed task. */
|
|
6
|
+
completed?: boolean;
|
|
7
|
+
/** Adds pointer cursor + accent hover ring. */
|
|
8
|
+
interactive?: boolean;
|
|
9
|
+
/** Grab cursor, for drag sources — pair with `interactive`. */
|
|
10
|
+
draggable?: boolean;
|
|
11
|
+
/** Suppresses the hover ring while a drag is in progress. */
|
|
12
|
+
dragging?: boolean;
|
|
13
|
+
/** Card fills its container width instead of a fixed width. */
|
|
14
|
+
fluid?: boolean;
|
|
15
|
+
children: ReactNode;
|
|
16
|
+
}
|
|
17
|
+
export declare function Card({ stacked, completed, interactive, draggable, dragging, fluid, children, ...rest }: CardProps): import("react").JSX.Element;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ChangeEvent } from 'react';
|
|
2
|
+
interface CheckboxProps {
|
|
3
|
+
checked: boolean;
|
|
4
|
+
onChange: (e: ChangeEvent<HTMLInputElement>) => void;
|
|
5
|
+
ariaLabel?: string;
|
|
6
|
+
className?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function Checkbox({ checked, onChange, ariaLabel, className }: CheckboxProps): import("react").JSX.Element;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
interface FilterSectionProps<T extends string> {
|
|
2
|
+
label: string;
|
|
3
|
+
options: T[];
|
|
4
|
+
optionLabel: (opt: T) => string;
|
|
5
|
+
activeSet: Set<T>;
|
|
6
|
+
onToggle: (opt: T) => void;
|
|
7
|
+
onSetAll?: (opts: T[]) => void;
|
|
8
|
+
searchable?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare function FilterSection<T extends string>({ label, options, optionLabel, activeSet, onToggle, onSetAll, searchable, }: FilterSectionProps<T>): import("react").JSX.Element;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { HTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
interface MenuProps extends Omit<HTMLAttributes<HTMLDivElement>, 'className'> {
|
|
3
|
+
children: ReactNode;
|
|
4
|
+
}
|
|
5
|
+
export declare function Menu({ children, ...rest }: MenuProps): import("react").JSX.Element;
|
|
6
|
+
export declare function MenuDivider(): import("react").JSX.Element;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ButtonHTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
interface MenuItemProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'className'> {
|
|
3
|
+
icon?: ReactNode;
|
|
4
|
+
trailing?: ReactNode;
|
|
5
|
+
selected?: boolean;
|
|
6
|
+
destructive?: boolean;
|
|
7
|
+
children: ReactNode;
|
|
8
|
+
}
|
|
9
|
+
export declare function MenuItem({ icon, trailing, selected, destructive, children, ...rest }: MenuItemProps): import("react").JSX.Element;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ChangeEvent } from 'react';
|
|
2
|
+
interface RadioButtonProps {
|
|
3
|
+
checked: boolean;
|
|
4
|
+
onChange: (e: ChangeEvent<HTMLInputElement>) => void;
|
|
5
|
+
name?: string;
|
|
6
|
+
value?: string;
|
|
7
|
+
ariaLabel?: string;
|
|
8
|
+
className?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function RadioButton({ checked, onChange, name, value, ariaLabel, className }: RadioButtonProps): import("react").JSX.Element;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
type TabsVariant = 'line' | 'box';
|
|
3
|
+
interface TabItem {
|
|
4
|
+
value: string;
|
|
5
|
+
label: ReactNode;
|
|
6
|
+
icon?: ReactNode;
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
}
|
|
9
|
+
interface TabsProps {
|
|
10
|
+
items: TabItem[];
|
|
11
|
+
value: string;
|
|
12
|
+
onChange: (value: string) => void;
|
|
13
|
+
variant?: TabsVariant;
|
|
14
|
+
'aria-label'?: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function Tabs({ items, value, onChange, variant, ...rest }: TabsProps): import("react").JSX.Element;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { HTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
type TagVariant = 'neutral' | 'pill' | 'accent' | 'success' | 'danger' | 'count';
|
|
3
|
+
interface TagProps extends Omit<HTMLAttributes<HTMLSpanElement>, 'className'> {
|
|
4
|
+
variant?: TagVariant;
|
|
5
|
+
children: ReactNode;
|
|
6
|
+
}
|
|
7
|
+
export declare function Tag({ variant, children, ...rest }: TagProps): import("react").JSX.Element;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { InputHTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
type TextFieldSize = 'sm' | 'base' | 'lg';
|
|
3
|
+
interface TextFieldProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'className' | 'size'> {
|
|
4
|
+
label?: string;
|
|
5
|
+
helperText?: string;
|
|
6
|
+
error?: string;
|
|
7
|
+
size?: TextFieldSize;
|
|
8
|
+
leadingIcon?: ReactNode;
|
|
9
|
+
}
|
|
10
|
+
export declare function TextField({ label, helperText, error, size, leadingIcon, id, ...rest }: TextFieldProps): import("react").JSX.Element;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
interface ToolbarProps {
|
|
3
|
+
searchValue?: string;
|
|
4
|
+
onSearchChange?: (value: string) => void;
|
|
5
|
+
placeholder?: string;
|
|
6
|
+
/** Text shown in the keyboard-shortcut badge, e.g. "⌘K". Omit to hide the badge. */
|
|
7
|
+
shortcutLabel?: string;
|
|
8
|
+
/** Focuses the search input when Cmd/Ctrl + the shortcut key is pressed. */
|
|
9
|
+
shortcutKey?: string;
|
|
10
|
+
/** Right-side content — filter/sort controls, actions, etc. */
|
|
11
|
+
children?: ReactNode;
|
|
12
|
+
}
|
|
13
|
+
export declare function Toolbar({ searchValue, onSearchChange, placeholder, shortcutLabel, shortcutKey, children, }: ToolbarProps): import("react").JSX.Element;
|
|
14
|
+
export {};
|
package/dist/index.css
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
._primary_1fqpm_1,._secondary_1fqpm_2,._tertiary_1fqpm_3,._dangerous_1fqpm_4{isolation:isolate;letter-spacing:.01em;cursor:pointer;border:none;justify-content:center;align-items:center;gap:8px;font-family:inherit;font-weight:450;transition:color .2s,transform .2s ease-out;display:inline-flex;position:relative;overflow:hidden}._primary_1fqpm_1:active:not(:disabled),._secondary_1fqpm_2:active:not(:disabled),._tertiary_1fqpm_3:active:not(:disabled),._dangerous_1fqpm_4:active:not(:disabled){transform:scale(.95)}._sm_1fqpm_28{border-radius:10px;padding:8px 12px;font-size:.8rem}._base_1fqpm_33{border-radius:12px;padding:12px 16px;font-size:.9rem}._lg_1fqpm_38{border-radius:14px;padding:16px 22px;font-size:1rem}._icon_1fqpm_44{flex-shrink:0;justify-content:center;align-items:center;width:16px;height:16px;display:flex}._icon_1fqpm_44 svg{width:100%;height:100%}._iconOnly_1fqpm_57{aspect-ratio:1;box-sizing:border-box}._iconOnly_1fqpm_57._sm_1fqpm_28{padding:8px}._iconOnly_1fqpm_57._base_1fqpm_33{padding:12px}._iconOnly_1fqpm_57._lg_1fqpm_38{padding:16px}._primary_1fqpm_1:before,._secondary_1fqpm_2:before,._tertiary_1fqpm_3:before,._dangerous_1fqpm_4:before{content:"";aspect-ratio:1;z-index:-1;pointer-events:none;border-radius:50%;width:24%;transition:transform .3s cubic-bezier(.39,.575,.565,1);position:absolute;bottom:0;left:50%;transform:translate(-50%,100%)scale(1)}._primary_1fqpm_1:hover:before,._secondary_1fqpm_2:hover:before,._tertiary_1fqpm_3:hover:before,._dangerous_1fqpm_4:hover:before{transform:translate(-50%,15%)scale(8)}._primary_1fqpm_1{background:var(--brand-dark);color:#fff;letter-spacing:.02em;font-weight:400}._primary_1fqpm_1:before{background:#ffffff14}._primary_1fqpm_1:active:not(:disabled):before{background:#00000014}._secondary_1fqpm_2{background:var(--surface-muted);color:var(--text-primary)}._secondary_1fqpm_2:before{background:rgba(var(--brand-main-rgb), .16)}._secondary_1fqpm_2:active:not(:disabled):before{background:rgba(var(--brand-main-rgb), .28)}._secondary_1fqpm_2:hover{color:var(--brand-main)}._tertiary_1fqpm_3{color:var(--text-secondary);background:0 0}._tertiary_1fqpm_3:before{background:rgba(var(--brand-main-rgb), .16)}._tertiary_1fqpm_3:active:not(:disabled):before{background:rgba(var(--brand-main-rgb), .28)}._tertiary_1fqpm_3:hover,._tertiary_1fqpm_3:active:not(:disabled){background:var(--bg)}._tertiary_1fqpm_3:hover{color:var(--brand-main)}._dangerous_1fqpm_4{background:var(--danger-bg);color:var(--danger-text-dark)}._dangerous_1fqpm_4:before{background:rgba(var(--danger-rgb), .16)}._dangerous_1fqpm_4:active:not(:disabled):before{background:rgba(var(--danger-rgb), .28)}._primary_1fqpm_1:disabled,._secondary_1fqpm_2:disabled,._tertiary_1fqpm_3:disabled,._dangerous_1fqpm_4:disabled{background:var(--disabled-bg);color:var(--disabled-text);cursor:not-allowed}._primary_1fqpm_1:disabled:hover,._secondary_1fqpm_2:disabled:hover,._tertiary_1fqpm_3:disabled:hover,._dangerous_1fqpm_4:disabled:hover{color:var(--disabled-text)}._primary_1fqpm_1:disabled:before,._secondary_1fqpm_2:disabled:before,._tertiary_1fqpm_3:disabled:before,._dangerous_1fqpm_4:disabled:before{display:none}._wrap_ewoh2_1{flex:0 0 220px;width:220px;position:relative}._wrap_ewoh2_1:hover{z-index:10}._fluid_ewoh2_9{flex:none;width:100%}._backing_ewoh2_14{background:var(--card-surface);height:10px;box-shadow:inset 0 0 0 1px var(--border);z-index:0;border-radius:0 0 14px 14px;position:absolute;bottom:-4px;left:6px;right:6px}._backing_ewoh2_14._completed_ewoh2_25{background:var(--success-bg);box-shadow:inset 0 0 0 1px #bfe3cc}._card_ewoh2_30{z-index:1;box-sizing:border-box;background:var(--card-surface);cursor:default;border-radius:16px;width:100%;padding:12px 14px;transition:box-shadow .2s;position:relative;box-shadow:inset 0 0 0 1px #efefef,0 1px 2px #1018200a}._card_ewoh2_30._interactive_ewoh2_44{cursor:pointer}._card_ewoh2_30._grabbable_ewoh2_47{cursor:grab}._card_ewoh2_30._grabbable_ewoh2_47:active{cursor:grabbing}._card_ewoh2_30._dragging_ewoh2_53,._card_ewoh2_30._dragging_ewoh2_53:hover{box-shadow:inset 0 0 0 1px #efefef,0 1px 2px #1018200a}._card_ewoh2_30._interactive_ewoh2_44:hover{box-shadow:inset 0 0 0 1px #efefef, 0 0 0 2px var(--brand-main)}._card_ewoh2_30._completed_ewoh2_25{background:var(--success-bg);box-shadow:inset 0 0 0 1px #bfe3cc,0 1px 2px #1018200a,0 2px 8px #1018200f}._neutral_c7c7e_1,._pill_c7c7e_2,._accent_c7c7e_3,._success_c7c7e_4,._danger_c7c7e_5,._count_c7c7e_6{white-space:nowrap;align-items:center;font-weight:500;display:inline-flex}._neutral_c7c7e_1{color:var(--text-tertiary);background:var(--bg);border-radius:6px;padding:2px 7px;font-size:.75rem}._pill_c7c7e_2{background:var(--card-surface);box-shadow:inset 0 0 0 1px var(--border);color:var(--text-tertiary);border-radius:999px;padding:3px 11px;font-size:.8rem}._accent_c7c7e_3{background:var(--brand-bg);color:var(--brand-dark);border-radius:999px;padding:3px 11px;font-size:.8rem}._success_c7c7e_4{background:var(--success-bg);color:var(--success-text);border-radius:999px;padding:3px 11px;font-size:.8rem}._danger_c7c7e_5{color:var(--danger-text);background:var(--danger-bg);border-radius:6px;padding:2px 7px;font-size:.75rem}._count_c7c7e_6{background:var(--brand-main);color:#fff;text-align:center;border-radius:999px;justify-content:center;min-width:16px;height:16px;padding:0 4px;font-size:.65rem;line-height:16px}._toolbar_1rsvo_1{background:var(--card-surface);box-shadow:inset 0 0 0 1px var(--border), 0 1px 2px #1018200a, 0 2px 8px #1018200f;border-radius:16px;justify-content:space-between;align-items:center;gap:16px;padding:0 8px;display:flex}._searchWrap_1rsvo_14{flex:1;min-width:0;position:relative}._searchWrap_1rsvo_14:after{content:"";background:var(--brand-main);opacity:0;pointer-events:none;height:2px;position:absolute;bottom:0;left:36px;right:0}._searchWrap_1rsvo_14:focus-within:after{opacity:1}._searchIcon_1rsvo_33{width:16px;height:16px;color:var(--text-tertiary);pointer-events:none;position:absolute;top:50%;left:12px;transform:translateY(-53%)}._searchIcon_1rsvo_33 svg{width:100%;height:100%}._search_1rsvo_14{box-sizing:border-box;width:100%;color:var(--text-primary);box-shadow:inset -1px 0 0 var(--border);background:0 0;border:none;padding:16px 52px 16px 36px;font-family:inherit;font-size:1rem}._search_1rsvo_14:focus{outline:none}._searchShortcut_1rsvo_61{background:var(--bg);color:var(--text-tertiary);letter-spacing:.02em;pointer-events:none;border-radius:6px;justify-content:center;align-items:center;padding:2px 6px;font-size:.75rem;font-weight:600;display:flex;position:absolute;top:50%;right:8px;transform:translateY(-50%)}._controls_1rsvo_78{flex:none;align-items:center;display:flex}._checkbox_veqkz_1{cursor:pointer;flex-shrink:0;justify-content:center;align-items:center;width:16px;height:16px;display:inline-flex;position:relative}._input_veqkz_11{opacity:0;cursor:pointer;margin:0;position:absolute;inset:0}._box_veqkz_18{background:var(--surface-sunken);width:16px;height:16px;box-shadow:inset 0 0 0 1px var(--border);border-radius:6px;justify-content:center;align-items:center;transition:background-color .2s cubic-bezier(0,0,.2,1),box-shadow .2s cubic-bezier(0,0,.2,1),transform .1s cubic-bezier(0,0,.2,1);display:flex}._input_veqkz_11:hover+._box_veqkz_18{box-shadow:inset 0 0 0 1px var(--brand-main)}._input_veqkz_11:focus-visible+._box_veqkz_18{outline:2px solid var(--brand-main);outline-offset:2px}._input_veqkz_11:active+._box_veqkz_18{transform:scale(.88)}._input_veqkz_11:checked+._box_veqkz_18{background:var(--brand-main);box-shadow:inset 0 0 0 1px var(--brand-main)}._icon_veqkz_46{width:10px;height:10px;overflow:visible}._icon_veqkz_46 polyline{fill:none;stroke:#fff;stroke-width:2.5px;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:22;stroke-dashoffset:22px;transition:stroke-dashoffset .2s cubic-bezier(.4,0,.2,1)}._input_veqkz_11:checked+._box_veqkz_18 ._icon_veqkz_46 polyline{stroke-dashoffset:0}._radio_7q2jv_1{cursor:pointer;flex-shrink:0;justify-content:center;align-items:center;width:16px;height:16px;display:inline-flex;position:relative}._input_7q2jv_11{opacity:0;cursor:pointer;margin:0;position:absolute;inset:0}._circle_7q2jv_18{background:var(--surface-sunken);width:16px;height:16px;box-shadow:inset 0 0 0 1px var(--border);border-radius:50%;justify-content:center;align-items:center;transition:background-color .2s cubic-bezier(0,0,.2,1),box-shadow .2s cubic-bezier(0,0,.2,1),transform .1s cubic-bezier(0,0,.2,1);display:flex}._input_7q2jv_11:hover+._circle_7q2jv_18{box-shadow:inset 0 0 0 1px var(--brand-main)}._input_7q2jv_11:focus-visible+._circle_7q2jv_18{outline:2px solid var(--brand-main);outline-offset:2px}._input_7q2jv_11:active+._circle_7q2jv_18{transform:scale(.88)}._input_7q2jv_11:checked+._circle_7q2jv_18{background:var(--brand-main);box-shadow:inset 0 0 0 1px var(--brand-main)}._dot_7q2jv_46{background:#fff;border-radius:50%;width:6px;height:6px;transition:transform .2s cubic-bezier(.4,0,.2,1);transform:scale(0)}._input_7q2jv_11:checked+._circle_7q2jv_18 ._dot_7q2jv_46{transform:scale(1)}._field_133ye_1{flex-direction:column;gap:6px;display:flex}._label_133ye_6{color:var(--text-primary);padding-left:8px;font-size:.85rem;font-weight:550}._inputWrap_133ye_12{background:var(--card-surface);box-shadow:inset 0 0 0 1px var(--border-input);align-items:center;transition:box-shadow .2s ease-out;display:flex;position:relative}._inputWrap_133ye_12:focus-within{box-shadow:inset 0 0 0 0 var(--border-input), 0 0 0 2px var(--brand-main)}._errorWrap_133ye_25,._errorWrap_133ye_25:focus-within{box-shadow:inset 0 0 0 1px var(--danger-text)}._inputWrap_133ye_12:has(._input_133ye_12:disabled){background:var(--surface-muted)}._sm_133ye_33{border-radius:10px}._sm_133ye_33 ._input_133ye_12{padding:8px 12px;font-size:.8rem}._base_133ye_40{border-radius:12px}._base_133ye_40 ._input_133ye_12{padding:12px 14px;font-size:.9rem}._lg_133ye_47{border-radius:14px}._lg_133ye_47 ._input_133ye_12{padding:16px;font-size:1rem}._inputWrap_133ye_12:has(._icon_133ye_54) ._input_133ye_12{padding-left:8px}._icon_133ye_54{width:16px;height:16px;color:var(--text-tertiary);flex-shrink:0;justify-content:center;align-items:center;margin-left:12px;display:flex}._icon_133ye_54 svg{width:100%;height:100%}._input_133ye_12{box-sizing:border-box;min-width:0;color:var(--text-primary);background:0 0;border:none;flex:1;font-family:inherit;font-weight:450}._input_133ye_12:focus{outline:none}._input_133ye_12::placeholder{color:var(--text-tertiary)}._input_133ye_12:disabled{color:var(--disabled-text);cursor:not-allowed}._helperText_133ye_92{color:var(--text-tertiary);padding-left:8px;font-size:.78rem}._errorText_133ye_97{color:var(--danger-text);font-size:.78rem}._menu_471l2_1{box-sizing:border-box;background:var(--card-surface);width:fit-content;min-width:180px;box-shadow:inset 0 0 0 1px var(--border), 0 8px 24px #0000001f;border-radius:12px;flex-direction:column;gap:2px;padding:4px;display:flex}._divider_471l2_15{background:var(--border);height:1px;margin:4px 6px}._item_ihchz_1{box-sizing:border-box;width:100%;color:var(--text-primary);text-align:left;cursor:pointer;background:0 0;border:none;border-radius:8px;align-items:center;gap:8px;padding:8px 10px;font-family:inherit;font-size:.9rem;transition:background .15s ease-out,color .15s ease-out;display:flex}._item_ihchz_1:hover:not(:disabled){background:var(--bg)}._item_ihchz_1:active:not(:disabled){background:var(--brand-bg)}._item_ihchz_1:focus-visible{outline:2px solid var(--brand-main);outline-offset:-2px}._item_ihchz_1:disabled{color:var(--disabled-text);cursor:not-allowed}._icon_ihchz_34{width:16px;height:16px;color:var(--text-tertiary);flex-shrink:0;justify-content:center;align-items:center;display:flex}._icon_ihchz_34 svg{width:100%;height:100%}._label_ihchz_47{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}._trailing_ihchz_54{color:var(--text-tertiary);flex-shrink:0;font-size:.8rem}._selected_ihchz_59{background:var(--brand-bg);color:var(--brand-dark)}._selected_ihchz_59 ._icon_ihchz_34{color:var(--brand-dark)}._destructive_ihchz_66,._destructive_ihchz_66 ._icon_ihchz_34{color:var(--danger-text)}._destructive_ihchz_66:hover:not(:disabled){background:var(--danger-bg)}._highlight_1anli_1{background:var(--brand-bg);color:var(--brand-dark);border-radius:3px;padding:0 1px}._group_51gk7_1{position:relative}._btn_51gk7_4{color:var(--text-primary);cursor:pointer;background:0 0;border:none;border-radius:12px;align-items:center;gap:6px;padding:12px;font-family:inherit;font-size:1rem;transition:background .2s ease-out,box-shadow .2s ease-out,transform .2s ease-out;display:flex}._btn_51gk7_4:hover{background:#0a0a0b0a}._btn_51gk7_4:active{background:var(--brand-bg);transform:scale(.95);box-shadow:inset 0 2px 1px #008cd840}._caret_51gk7_29{color:var(--text-tertiary);align-items:center;display:flex}._caret_51gk7_29 svg{width:14px;height:14px}._label_51gk7_38{color:var(--text-secondary)}._badge_51gk7_41{background:var(--brand-main,#0a84d8);color:#fff;text-align:center;border-radius:999px;min-width:16px;height:16px;padding:0 4px;font-size:.65rem;font-weight:600;line-height:16px;position:absolute;top:2px;right:2px}._value_51gk7_56{color:var(--text-primary);font-weight:500}._panel_51gk7_60{width:fit-content;min-width:220px;max-height:280px;box-shadow:inset 0 0 0 1px var(--border), 0 8px 24px #0000001f;z-index:50;background:#fff;border-radius:12px;display:none;position:absolute;top:calc(100% + 6px);left:0;overflow-y:auto}._panel_51gk7_60._open_51gk7_76{display:block}._panelRight_51gk7_79{left:auto;right:0}._panelWide_51gk7_83{min-width:260px;padding-bottom:4px}._sectionHeader_51gk7_87{justify-content:space-between;align-items:center;gap:8px;padding:12px 14px 4px;display:flex}._sectionLabel_51gk7_94{color:var(--text-tertiary);text-transform:uppercase;letter-spacing:.02em;font-size:.75rem;font-weight:600}._allToggle_51gk7_101{color:var(--brand-main,#0a84d8);cursor:pointer;background:0 0;border:none;padding:0;font-family:inherit;font-size:.75rem;font-weight:600}._allToggle_51gk7_101:hover{text-decoration:underline}._divider_51gk7_114{background:var(--border);height:1px;margin:4px 0}._option_51gk7_119{cursor:pointer;border-radius:8px;align-items:center;gap:8px;padding:8px;font-size:1rem;display:flex}._option_51gk7_119:hover{background:var(--bg)}._search_51gk7_131{box-sizing:border-box;width:calc(100% - 16px);box-shadow:inset 0 0 0 1px var(--border-input);border:none;border-radius:8px;margin:8px 8px 0;padding:8px 12px;font-family:inherit;font-size:1rem}._search_51gk7_131:focus{box-shadow:inset 0 0 0 1px var(--brand-main);outline:none}._optionsList_51gk7_147{padding:4px}._empty_51gk7_150{color:var(--text-tertiary);padding:7px 8px;font-size:.85rem}._sidebar_1fx39_1{background:var(--surface-sunken);box-sizing:border-box;border-radius:16px 16px 0 0;flex-direction:column;flex:0 0 256px;gap:4px;width:256px;padding:24px 16px 24px 24px;display:flex;overflow-y:auto;box-shadow:1px 0 #0a0a0b08,0 -1px #0a0a0b0d}._title_1fx39_16{letter-spacing:-.01em;margin:0 0 16px 8px;font-size:1.15rem;font-weight:500}._navLink_1fx39_22{color:var(--text-secondary);border-radius:8px;justify-content:space-between;align-items:center;gap:8px;padding:8px;font-size:.9rem;font-weight:500;text-decoration:none;display:flex}._navLink_1fx39_22:hover{background:var(--card-surface);color:var(--text-primary)}._count_1fx39_38{color:var(--text-tertiary);font-size:.78rem;font-weight:500}._line_q3udz_1,._box_q3udz_2{align-items:center;gap:4px;display:inline-flex}._tab_q3udz_8{isolation:isolate;cursor:pointer;white-space:nowrap;border:none;align-items:center;gap:6px;font-family:inherit;font-weight:450;transition:color .15s ease-out,background .15s ease-out,box-shadow .15s ease-out;display:inline-flex;position:relative;overflow:hidden}._tab_q3udz_8:before{content:"";aspect-ratio:1;z-index:-1;pointer-events:none;background:rgba(var(--brand-main-rgb), .16);border-radius:50%;width:40%;transition:transform .3s cubic-bezier(.39,.575,.565,1);position:absolute;bottom:0;left:50%;transform:translate(-50%,100%)scale(1)}._tab_q3udz_8:hover:not(:disabled):before{transform:translate(-50%,15%)scale(4)}._tab_q3udz_8:active:not(:disabled):before{background:rgba(var(--brand-main-rgb), .28)}._tab_q3udz_8:disabled{color:var(--disabled-text);cursor:not-allowed}._tab_q3udz_8:disabled:before,._tab_q3udz_8._selected_q3udz_52:hover:before{display:none}._tab_q3udz_8:focus-visible{outline:2px solid var(--brand-main);outline-offset:2px}._icon_q3udz_61{flex-shrink:0;justify-content:center;align-items:center;width:16px;height:16px;display:flex}._icon_q3udz_61 svg{width:100%;height:100%}._line_q3udz_1{box-shadow:inset 0 -1px 0 0 var(--border)}._line_q3udz_1 ._tab_q3udz_8{color:var(--text-secondary);background:0 0;padding:10px 4px;font-size:.9rem;box-shadow:inset 0 -2px #0000}._line_q3udz_1 ._tab_q3udz_8:hover:not(:disabled){color:var(--brand-main)}._line_q3udz_1 ._tab_q3udz_8._selected_q3udz_52{color:var(--text-primary);box-shadow:inset 0 -2px 0 0 var(--brand-main)}._box_q3udz_2{background:#1018200a;border-radius:10px;gap:4px;padding:4px}._box_q3udz_2 ._tab_q3udz_8{color:var(--text-secondary);background:0 0;border-radius:8px;padding:8px 14px;font-size:.9rem}._box_q3udz_2 ._tab_q3udz_8:hover:not(:disabled){color:var(--brand-main)}._box_q3udz_2 ._tab_q3udz_8._selected_q3udz_52{background:var(--card-surface);color:var(--text-primary);box-shadow:0 0 1px .5px var(--border);font-weight:500}:root{--brand-main:#0090d9;--brand-dark:#007ebd;--brand-bg:#e0f5ff;--brand-main-rgb:0, 144, 217;--brand-main-5:rgba(var(--brand-main-rgb), .05);--brand-main-10:rgba(var(--brand-main-rgb), .1);--brand-main-20:rgba(var(--brand-main-rgb), .2);--brand-main-30:rgba(var(--brand-main-rgb), .3);--brand-main-50:rgba(var(--brand-main-rgb), .5);--brand-main-75:rgba(var(--brand-main-rgb), .75);--text-primary:#090b0b;--text-secondary:#5c5f61;--text-tertiary:#666e73;--bg:#f7f7f7;--card-surface:#fff;--surface-sunken:#f8f9fa;--surface-muted:#ececec;--border:#e0e0e0;--border-input:#e0e0e0;--danger-bg:#fdeaea;--danger-text:#d92d20;--danger-text-dark:#b91c1c;--danger-rgb:217, 45, 32;--success-bg:#e3f6ea;--success-text:#2f8a52;--warning-text:#9a6400;--disabled-bg:#c4c4c4;--disabled-text:#8a8a8a;--font-family-base:"Inter", sans-serif;--font-size-sm:.75rem;--font-size-base:.875rem;--font-size-lg:1rem;--font-weight-regular:400;--font-weight-bold:500;--line-height-base:1.5;--line-height-tight:1.25}.text-base{font-family:var(--font-family-base);font-size:var(--font-size-base);font-weight:var(--font-weight-regular);line-height:var(--line-height-base)}.text-bold{font-weight:var(--font-weight-bold)}.text-sm{font-size:var(--font-size-sm)}.text-lg{font-size:var(--font-size-lg)}.text-2-line{line-height:var(--line-height-tight)}
|
|
2
|
+
/*$vite$:1*/
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export { Button } from './components/Button';
|
|
2
|
+
export { Card } from './components/Card';
|
|
3
|
+
export { Tag } from './components/Tag';
|
|
4
|
+
export { Toolbar } from './components/Toolbar';
|
|
5
|
+
export { Checkbox } from './components/Checkbox';
|
|
6
|
+
export { RadioButton } from './components/RadioButton';
|
|
7
|
+
export { TextField } from './components/TextField';
|
|
8
|
+
export { Menu, MenuDivider } from './components/Menu';
|
|
9
|
+
export { MenuItem } from './components/MenuItem';
|
|
10
|
+
export { HighlightText } from './components/HighlightText';
|
|
11
|
+
export { FilterSection } from './components/FilterSection';
|
|
12
|
+
export { UiElementsSidebar } from './components/UiElementsSidebar';
|
|
13
|
+
export { Tabs } from './components/Tabs';
|
|
14
|
+
export { formatDuration, formatDurationHMS } from './utils/format';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,580 @@
|
|
|
1
|
+
import { Fragment as e, jsx as t, jsxs as n } from "react/jsx-runtime";
|
|
2
|
+
import { Fragment as r, createContext as i, createElement as a, forwardRef as o, useContext as s, useEffect as c, useId as l, useRef as u, useState as d } from "react";
|
|
3
|
+
var f = {
|
|
4
|
+
primary: "_primary_1fqpm_1",
|
|
5
|
+
secondary: "_secondary_1fqpm_2",
|
|
6
|
+
tertiary: "_tertiary_1fqpm_3",
|
|
7
|
+
dangerous: "_dangerous_1fqpm_4",
|
|
8
|
+
sm: "_sm_1fqpm_28",
|
|
9
|
+
base: "_base_1fqpm_33",
|
|
10
|
+
lg: "_lg_1fqpm_38",
|
|
11
|
+
icon: "_icon_1fqpm_44",
|
|
12
|
+
iconOnly: "_iconOnly_1fqpm_57"
|
|
13
|
+
};
|
|
14
|
+
//#endregion
|
|
15
|
+
//#region src/components/Button.tsx
|
|
16
|
+
function p({ variant: e = "primary", size: r = "base", leadingIcon: i, trailingIcon: a, children: o, ...s }) {
|
|
17
|
+
let c = !o && !!i;
|
|
18
|
+
return /* @__PURE__ */ n("button", {
|
|
19
|
+
type: "button",
|
|
20
|
+
className: `${f[e]} ${f[r]}${c ? ` ${f.iconOnly}` : ""}`,
|
|
21
|
+
...s,
|
|
22
|
+
children: [
|
|
23
|
+
i && /* @__PURE__ */ t("span", {
|
|
24
|
+
className: f.icon,
|
|
25
|
+
children: i
|
|
26
|
+
}),
|
|
27
|
+
o,
|
|
28
|
+
a && /* @__PURE__ */ t("span", {
|
|
29
|
+
className: f.icon,
|
|
30
|
+
children: a
|
|
31
|
+
})
|
|
32
|
+
]
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
var m = {
|
|
36
|
+
wrap: "_wrap_ewoh2_1",
|
|
37
|
+
fluid: "_fluid_ewoh2_9",
|
|
38
|
+
backing: "_backing_ewoh2_14",
|
|
39
|
+
completed: "_completed_ewoh2_25",
|
|
40
|
+
card: "_card_ewoh2_30",
|
|
41
|
+
interactive: "_interactive_ewoh2_44",
|
|
42
|
+
grabbable: "_grabbable_ewoh2_47",
|
|
43
|
+
dragging: "_dragging_ewoh2_53"
|
|
44
|
+
};
|
|
45
|
+
//#endregion
|
|
46
|
+
//#region src/components/Card.tsx
|
|
47
|
+
function h({ stacked: e, completed: r, interactive: i, draggable: a, dragging: o, fluid: s, children: c, ...l }) {
|
|
48
|
+
return /* @__PURE__ */ n("div", {
|
|
49
|
+
className: `${m.wrap} ${s ? m.fluid : ""}`,
|
|
50
|
+
children: [e && /* @__PURE__ */ t("div", { className: `${m.backing} ${r ? m.completed : ""}` }), /* @__PURE__ */ t("div", {
|
|
51
|
+
className: [
|
|
52
|
+
m.card,
|
|
53
|
+
r ? m.completed : "",
|
|
54
|
+
i ? m.interactive : "",
|
|
55
|
+
a ? m.grabbable : "",
|
|
56
|
+
o ? m.dragging : ""
|
|
57
|
+
].filter(Boolean).join(" "),
|
|
58
|
+
...l,
|
|
59
|
+
children: c
|
|
60
|
+
})]
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
var g = {
|
|
64
|
+
neutral: "_neutral_c7c7e_1",
|
|
65
|
+
pill: "_pill_c7c7e_2",
|
|
66
|
+
accent: "_accent_c7c7e_3",
|
|
67
|
+
success: "_success_c7c7e_4",
|
|
68
|
+
danger: "_danger_c7c7e_5",
|
|
69
|
+
count: "_count_c7c7e_6"
|
|
70
|
+
};
|
|
71
|
+
//#endregion
|
|
72
|
+
//#region src/components/Tag.tsx
|
|
73
|
+
function _({ variant: e = "neutral", children: n, ...r }) {
|
|
74
|
+
return /* @__PURE__ */ t("span", {
|
|
75
|
+
className: g[e],
|
|
76
|
+
...r,
|
|
77
|
+
children: n
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
//#endregion
|
|
81
|
+
//#region node_modules/lucide-react/dist/esm/shared/src/utils/toKebabCase.mjs
|
|
82
|
+
var v = (e) => e?.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
|
|
83
|
+
//#endregion
|
|
84
|
+
//#region node_modules/lucide-react/dist/esm/shared/src/utils/toLucideIconData.mjs
|
|
85
|
+
function y(e, t, n = []) {
|
|
86
|
+
if (t == null) throw Error("[lucide]: iconNode is required when icon name is used");
|
|
87
|
+
return {
|
|
88
|
+
name: v(e),
|
|
89
|
+
size: 24,
|
|
90
|
+
node: t,
|
|
91
|
+
...n.length > 0 ? { aliases: n } : {}
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
//#endregion
|
|
95
|
+
//#region node_modules/lucide-react/dist/esm/shared/src/utils/toCamelCase.mjs
|
|
96
|
+
var b = (e) => {
|
|
97
|
+
let t = "", n = !1;
|
|
98
|
+
for (let r of e) {
|
|
99
|
+
if (r === "-" || r === "_" || r <= " ") {
|
|
100
|
+
n = t.length > 0;
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
t.length === 0 ? t += r.toLowerCase() : t += n ? r.toUpperCase() : r, n = !1;
|
|
104
|
+
}
|
|
105
|
+
return t;
|
|
106
|
+
}, x = (e) => {
|
|
107
|
+
let t = b(e);
|
|
108
|
+
return t.charAt(0).toUpperCase() + t.slice(1);
|
|
109
|
+
}, S = (...e) => e.filter((e, t, n) => !!e && e.trim() !== "" && n.indexOf(e) === t).join(" ").trim(), C = {
|
|
110
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
111
|
+
width: 24,
|
|
112
|
+
height: 24,
|
|
113
|
+
viewBox: "0 0 24 24",
|
|
114
|
+
fill: "none",
|
|
115
|
+
stroke: "currentColor",
|
|
116
|
+
"stroke-width": 2,
|
|
117
|
+
"stroke-linecap": "round",
|
|
118
|
+
"stroke-linejoin": "round"
|
|
119
|
+
};
|
|
120
|
+
//#endregion
|
|
121
|
+
//#region node_modules/lucide-react/dist/esm/shared/src/build/buildLucideIconNode.mjs
|
|
122
|
+
function w(e) {
|
|
123
|
+
return e != null;
|
|
124
|
+
}
|
|
125
|
+
function T(e, t = {}) {
|
|
126
|
+
let n = t.attributeNames ?? {}, r = (e) => n[e] ?? e, i = e.size ?? e.width ?? C.width, a = e.size ?? e.height ?? C.height, o = e.aliases?.filter((e) => typeof e == "string" && e.trim() !== "").map((e) => `lucide-${e}`) ?? [], s = [...e.name ? [`lucide-${e.name}`] : [], ...o], c = t.className?.split(" ").filter(Boolean) ?? [], l = t.includeDefaultClasses === !1 ? S(...c) : S("lucide", ...s, ...c), u = t.absoluteStrokeWidth ? Number(t.strokeWidth ?? C["stroke-width"]) * Number(e.size ?? e.width ?? C.width) / Number(t.size ?? t.width ?? C.width) : t.strokeWidth ?? C["stroke-width"];
|
|
127
|
+
return [
|
|
128
|
+
"svg",
|
|
129
|
+
{
|
|
130
|
+
...Object.entries(C).reduce((e, [t, n]) => (e[r(t)] = n, e), {}),
|
|
131
|
+
..."color" in t && t.color && { [r("stroke")]: t.color },
|
|
132
|
+
..."size" in t && w(t.size) && {
|
|
133
|
+
[r("width")]: t.size,
|
|
134
|
+
[r("height")]: t.size
|
|
135
|
+
},
|
|
136
|
+
..."width" in t && w(t.width) && { [r("width")]: t.width },
|
|
137
|
+
..."height" in t && w(t.height) && { [r("height")]: t.height },
|
|
138
|
+
[r("stroke-width")]: u,
|
|
139
|
+
...l && { [r("class")]: l },
|
|
140
|
+
[r("viewBox")]: `0 0 ${i} ${a}`,
|
|
141
|
+
...t.hasA11yProp === !1 ? { [r("aria-hidden")]: "true" } : {},
|
|
142
|
+
..."attributes" in t && t.attributes
|
|
143
|
+
},
|
|
144
|
+
e.node.map((e) => {
|
|
145
|
+
let [n, i, a] = e, o = t.nonScalingStroke ? {
|
|
146
|
+
[r("vector-effect")]: "non-scaling-stroke",
|
|
147
|
+
...i
|
|
148
|
+
} : i;
|
|
149
|
+
return a ? [
|
|
150
|
+
n,
|
|
151
|
+
o,
|
|
152
|
+
a
|
|
153
|
+
] : [n, o];
|
|
154
|
+
})
|
|
155
|
+
];
|
|
156
|
+
}
|
|
157
|
+
//#endregion
|
|
158
|
+
//#region node_modules/lucide-react/dist/esm/shared/src/build/buildLucideIconForReact.mjs
|
|
159
|
+
function E(e, t = {}) {
|
|
160
|
+
return T(e, {
|
|
161
|
+
...t,
|
|
162
|
+
attributeNames: {
|
|
163
|
+
...t.attributeNames,
|
|
164
|
+
class: "className",
|
|
165
|
+
"stroke-width": "strokeWidth",
|
|
166
|
+
"stroke-linecap": "strokeLinecap",
|
|
167
|
+
"stroke-linejoin": "strokeLinejoin",
|
|
168
|
+
"vector-effect": "vectorEffect"
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
//#endregion
|
|
173
|
+
//#region node_modules/lucide-react/dist/esm/shared/src/utils/hasA11yProp.mjs
|
|
174
|
+
var ee = (e) => {
|
|
175
|
+
for (let t in e) if (t.startsWith("aria-") || t === "role" || t === "title") return !0;
|
|
176
|
+
return !1;
|
|
177
|
+
}, D = i({}), O = () => s(D), k = o(({ color: e, size: t, width: n, height: r, strokeWidth: i, absoluteStrokeWidth: o, nonScalingStroke: s, className: c = "", children: l, iconNode: u = [], icon: d = {
|
|
178
|
+
node: u,
|
|
179
|
+
aliases: [],
|
|
180
|
+
size: 24
|
|
181
|
+
}, ...f }, p) => {
|
|
182
|
+
let { size: m = 24, strokeWidth: h = 2, absoluteStrokeWidth: g = !1, nonScalingStroke: _ = !1, color: v = "currentColor", className: y = "" } = O() ?? {}, b = !!l || ee(f), [x, C, w = []] = E(d, {
|
|
183
|
+
color: e ?? v,
|
|
184
|
+
width: n ?? t ?? m,
|
|
185
|
+
height: r ?? t ?? m,
|
|
186
|
+
strokeWidth: i ?? h,
|
|
187
|
+
absoluteStrokeWidth: o ?? g,
|
|
188
|
+
nonScalingStroke: s ?? _,
|
|
189
|
+
className: S(y, c),
|
|
190
|
+
hasA11yProp: b,
|
|
191
|
+
attributes: f
|
|
192
|
+
});
|
|
193
|
+
return a(x, {
|
|
194
|
+
ref: p,
|
|
195
|
+
...C
|
|
196
|
+
}, [...w.map(([e, t]) => a(e, t)), ...Array.isArray(l) ? l : [l]]);
|
|
197
|
+
});
|
|
198
|
+
//#endregion
|
|
199
|
+
//#region node_modules/lucide-react/dist/esm/createLucideIcon.mjs
|
|
200
|
+
function A(e, t = [], n = []) {
|
|
201
|
+
let r = typeof e == "string" ? y(e, t, n) : e, i = o(({ className: e, ...t }, n) => a(k, {
|
|
202
|
+
ref: n,
|
|
203
|
+
icon: r,
|
|
204
|
+
className: e,
|
|
205
|
+
...t
|
|
206
|
+
}));
|
|
207
|
+
return r.name && (i.displayName = x(r.name)), i;
|
|
208
|
+
}
|
|
209
|
+
//#endregion
|
|
210
|
+
//#region node_modules/lucide-react/dist/esm/icons/search.mjs
|
|
211
|
+
var j = {
|
|
212
|
+
name: "search",
|
|
213
|
+
size: 24,
|
|
214
|
+
node: [["path", {
|
|
215
|
+
d: "m21 21-4.34-4.34",
|
|
216
|
+
key: "14j7rj"
|
|
217
|
+
}], ["circle", {
|
|
218
|
+
cx: "11",
|
|
219
|
+
cy: "11",
|
|
220
|
+
r: "8",
|
|
221
|
+
key: "4ej97u"
|
|
222
|
+
}]]
|
|
223
|
+
};
|
|
224
|
+
j.node;
|
|
225
|
+
var M = A(j), N = {
|
|
226
|
+
toolbar: "_toolbar_1rsvo_1",
|
|
227
|
+
searchWrap: "_searchWrap_1rsvo_14",
|
|
228
|
+
searchIcon: "_searchIcon_1rsvo_33",
|
|
229
|
+
search: "_search_1rsvo_14",
|
|
230
|
+
searchShortcut: "_searchShortcut_1rsvo_61",
|
|
231
|
+
controls: "_controls_1rsvo_78"
|
|
232
|
+
};
|
|
233
|
+
//#endregion
|
|
234
|
+
//#region src/components/Toolbar.tsx
|
|
235
|
+
function P({ searchValue: e, onSearchChange: r, placeholder: i = "Search…", shortcutLabel: a = "⌘K", shortcutKey: o = "k", children: s }) {
|
|
236
|
+
let l = u(null);
|
|
237
|
+
return c(() => {
|
|
238
|
+
function e(e) {
|
|
239
|
+
(e.metaKey || e.ctrlKey) && e.key.toLowerCase() === o.toLowerCase() && (e.preventDefault(), l.current?.focus());
|
|
240
|
+
}
|
|
241
|
+
return window.addEventListener("keydown", e), () => window.removeEventListener("keydown", e);
|
|
242
|
+
}, [o]), /* @__PURE__ */ n("div", {
|
|
243
|
+
className: N.toolbar,
|
|
244
|
+
children: [/* @__PURE__ */ n("div", {
|
|
245
|
+
className: N.searchWrap,
|
|
246
|
+
children: [
|
|
247
|
+
/* @__PURE__ */ t("span", {
|
|
248
|
+
className: N.searchIcon,
|
|
249
|
+
children: /* @__PURE__ */ t(M, {})
|
|
250
|
+
}),
|
|
251
|
+
/* @__PURE__ */ t("input", {
|
|
252
|
+
ref: l,
|
|
253
|
+
type: "text",
|
|
254
|
+
className: N.search,
|
|
255
|
+
placeholder: i,
|
|
256
|
+
autoComplete: "off",
|
|
257
|
+
value: e,
|
|
258
|
+
onChange: (e) => r?.(e.target.value)
|
|
259
|
+
}),
|
|
260
|
+
a && /* @__PURE__ */ t("span", {
|
|
261
|
+
className: N.searchShortcut,
|
|
262
|
+
"aria-hidden": "true",
|
|
263
|
+
children: a
|
|
264
|
+
})
|
|
265
|
+
]
|
|
266
|
+
}), s && /* @__PURE__ */ t("div", {
|
|
267
|
+
className: N.controls,
|
|
268
|
+
children: s
|
|
269
|
+
})]
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
var F = {
|
|
273
|
+
checkbox: "_checkbox_veqkz_1",
|
|
274
|
+
input: "_input_veqkz_11",
|
|
275
|
+
box: "_box_veqkz_18",
|
|
276
|
+
icon: "_icon_veqkz_46"
|
|
277
|
+
};
|
|
278
|
+
//#endregion
|
|
279
|
+
//#region src/components/Checkbox.tsx
|
|
280
|
+
function I({ checked: e, onChange: r, ariaLabel: i, className: a }) {
|
|
281
|
+
return /* @__PURE__ */ n("label", {
|
|
282
|
+
className: `${F.checkbox} ${a ?? ""}`,
|
|
283
|
+
children: [/* @__PURE__ */ t("input", {
|
|
284
|
+
type: "checkbox",
|
|
285
|
+
className: F.input,
|
|
286
|
+
checked: e,
|
|
287
|
+
onChange: r,
|
|
288
|
+
"aria-label": i
|
|
289
|
+
}), /* @__PURE__ */ t("span", {
|
|
290
|
+
className: F.box,
|
|
291
|
+
children: /* @__PURE__ */ t("svg", {
|
|
292
|
+
className: F.icon,
|
|
293
|
+
viewBox: "0 0 17 18",
|
|
294
|
+
"aria-hidden": "true",
|
|
295
|
+
children: /* @__PURE__ */ t("polyline", { points: "1 9 7 14 15 4" })
|
|
296
|
+
})
|
|
297
|
+
})]
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
var L = {
|
|
301
|
+
radio: "_radio_7q2jv_1",
|
|
302
|
+
input: "_input_7q2jv_11",
|
|
303
|
+
circle: "_circle_7q2jv_18",
|
|
304
|
+
dot: "_dot_7q2jv_46"
|
|
305
|
+
};
|
|
306
|
+
//#endregion
|
|
307
|
+
//#region src/components/RadioButton.tsx
|
|
308
|
+
function R({ checked: e, onChange: r, name: i, value: a, ariaLabel: o, className: s }) {
|
|
309
|
+
return /* @__PURE__ */ n("label", {
|
|
310
|
+
className: `${L.radio} ${s ?? ""}`,
|
|
311
|
+
children: [/* @__PURE__ */ t("input", {
|
|
312
|
+
type: "radio",
|
|
313
|
+
className: L.input,
|
|
314
|
+
checked: e,
|
|
315
|
+
onChange: r,
|
|
316
|
+
name: i,
|
|
317
|
+
value: a,
|
|
318
|
+
"aria-label": o
|
|
319
|
+
}), /* @__PURE__ */ t("span", {
|
|
320
|
+
className: L.circle,
|
|
321
|
+
children: /* @__PURE__ */ t("span", { className: L.dot })
|
|
322
|
+
})]
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
var z = {
|
|
326
|
+
field: "_field_133ye_1",
|
|
327
|
+
label: "_label_133ye_6",
|
|
328
|
+
inputWrap: "_inputWrap_133ye_12",
|
|
329
|
+
errorWrap: "_errorWrap_133ye_25",
|
|
330
|
+
input: "_input_133ye_12",
|
|
331
|
+
sm: "_sm_133ye_33",
|
|
332
|
+
base: "_base_133ye_40",
|
|
333
|
+
lg: "_lg_133ye_47",
|
|
334
|
+
icon: "_icon_133ye_54",
|
|
335
|
+
helperText: "_helperText_133ye_92",
|
|
336
|
+
errorText: "_errorText_133ye_97"
|
|
337
|
+
};
|
|
338
|
+
//#endregion
|
|
339
|
+
//#region src/components/TextField.tsx
|
|
340
|
+
function B({ label: e, helperText: r, error: i, size: a = "base", leadingIcon: o, id: s, ...c }) {
|
|
341
|
+
let u = l(), d = s ?? u;
|
|
342
|
+
return /* @__PURE__ */ n("div", {
|
|
343
|
+
className: z.field,
|
|
344
|
+
children: [
|
|
345
|
+
e && /* @__PURE__ */ t("label", {
|
|
346
|
+
className: z.label,
|
|
347
|
+
htmlFor: d,
|
|
348
|
+
children: e
|
|
349
|
+
}),
|
|
350
|
+
/* @__PURE__ */ n("div", {
|
|
351
|
+
className: `${z.inputWrap} ${z[a]} ${i ? z.errorWrap : ""}`,
|
|
352
|
+
children: [o && /* @__PURE__ */ t("span", {
|
|
353
|
+
className: z.icon,
|
|
354
|
+
children: o
|
|
355
|
+
}), /* @__PURE__ */ t("input", {
|
|
356
|
+
id: d,
|
|
357
|
+
className: z.input,
|
|
358
|
+
...c
|
|
359
|
+
})]
|
|
360
|
+
}),
|
|
361
|
+
i ? /* @__PURE__ */ t("span", {
|
|
362
|
+
className: z.errorText,
|
|
363
|
+
children: i
|
|
364
|
+
}) : r ? /* @__PURE__ */ t("span", {
|
|
365
|
+
className: z.helperText,
|
|
366
|
+
children: r
|
|
367
|
+
}) : null
|
|
368
|
+
]
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
var V = {
|
|
372
|
+
menu: "_menu_471l2_1",
|
|
373
|
+
divider: "_divider_471l2_15"
|
|
374
|
+
};
|
|
375
|
+
//#endregion
|
|
376
|
+
//#region src/components/Menu.tsx
|
|
377
|
+
function H({ children: e, ...n }) {
|
|
378
|
+
return /* @__PURE__ */ t("div", {
|
|
379
|
+
role: "menu",
|
|
380
|
+
className: V.menu,
|
|
381
|
+
...n,
|
|
382
|
+
children: e
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
function U() {
|
|
386
|
+
return /* @__PURE__ */ t("div", {
|
|
387
|
+
className: V.divider,
|
|
388
|
+
role: "separator"
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
var W = {
|
|
392
|
+
item: "_item_ihchz_1",
|
|
393
|
+
icon: "_icon_ihchz_34",
|
|
394
|
+
label: "_label_ihchz_47",
|
|
395
|
+
trailing: "_trailing_ihchz_54",
|
|
396
|
+
selected: "_selected_ihchz_59",
|
|
397
|
+
destructive: "_destructive_ihchz_66"
|
|
398
|
+
};
|
|
399
|
+
//#endregion
|
|
400
|
+
//#region src/components/MenuItem.tsx
|
|
401
|
+
function G({ icon: e, trailing: r, selected: i, destructive: a, children: o, ...s }) {
|
|
402
|
+
let c = [
|
|
403
|
+
W.item,
|
|
404
|
+
i && W.selected,
|
|
405
|
+
a && W.destructive
|
|
406
|
+
].filter(Boolean).join(" ");
|
|
407
|
+
return /* @__PURE__ */ n("button", {
|
|
408
|
+
type: "button",
|
|
409
|
+
role: "menuitem",
|
|
410
|
+
className: c,
|
|
411
|
+
...s,
|
|
412
|
+
children: [
|
|
413
|
+
e && /* @__PURE__ */ t("span", {
|
|
414
|
+
className: W.icon,
|
|
415
|
+
children: e
|
|
416
|
+
}),
|
|
417
|
+
/* @__PURE__ */ t("span", {
|
|
418
|
+
className: W.label,
|
|
419
|
+
children: o
|
|
420
|
+
}),
|
|
421
|
+
r && /* @__PURE__ */ t("span", {
|
|
422
|
+
className: W.trailing,
|
|
423
|
+
children: r
|
|
424
|
+
})
|
|
425
|
+
]
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
var K = { highlight: "_highlight_1anli_1" };
|
|
429
|
+
//#endregion
|
|
430
|
+
//#region src/components/HighlightText.tsx
|
|
431
|
+
function q(e) {
|
|
432
|
+
return e.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
433
|
+
}
|
|
434
|
+
function J({ text: n, query: i }) {
|
|
435
|
+
if (!i) return /* @__PURE__ */ t(e, { children: n });
|
|
436
|
+
let a = n.split(RegExp(`(${q(i)})`, "ig"));
|
|
437
|
+
return /* @__PURE__ */ t(e, { children: a.map((e, n) => e.toLowerCase() === i.toLowerCase() ? /* @__PURE__ */ t("mark", {
|
|
438
|
+
className: K.highlight,
|
|
439
|
+
children: e
|
|
440
|
+
}, n) : /* @__PURE__ */ t(r, { children: e }, n)) });
|
|
441
|
+
}
|
|
442
|
+
var Y = {
|
|
443
|
+
group: "_group_51gk7_1",
|
|
444
|
+
btn: "_btn_51gk7_4",
|
|
445
|
+
caret: "_caret_51gk7_29",
|
|
446
|
+
label: "_label_51gk7_38",
|
|
447
|
+
badge: "_badge_51gk7_41",
|
|
448
|
+
value: "_value_51gk7_56",
|
|
449
|
+
panel: "_panel_51gk7_60",
|
|
450
|
+
open: "_open_51gk7_76",
|
|
451
|
+
panelRight: "_panelRight_51gk7_79",
|
|
452
|
+
panelWide: "_panelWide_51gk7_83",
|
|
453
|
+
sectionHeader: "_sectionHeader_51gk7_87",
|
|
454
|
+
sectionLabel: "_sectionLabel_51gk7_94",
|
|
455
|
+
allToggle: "_allToggle_51gk7_101",
|
|
456
|
+
divider: "_divider_51gk7_114",
|
|
457
|
+
option: "_option_51gk7_119",
|
|
458
|
+
search: "_search_51gk7_131",
|
|
459
|
+
optionsList: "_optionsList_51gk7_147",
|
|
460
|
+
empty: "_empty_51gk7_150"
|
|
461
|
+
};
|
|
462
|
+
//#endregion
|
|
463
|
+
//#region src/components/FilterSection.tsx
|
|
464
|
+
function X({ label: e, options: r, optionLabel: i, activeSet: a, onToggle: o, onSetAll: s, searchable: c }) {
|
|
465
|
+
let [l, u] = d(""), f = l.trim().toLowerCase(), p = f ? r.filter((e) => i(e).toLowerCase().includes(f)) : r, m = r.length > 0 && a.size === r.length;
|
|
466
|
+
return /* @__PURE__ */ n("div", { children: [
|
|
467
|
+
/* @__PURE__ */ n("div", {
|
|
468
|
+
className: Y.sectionHeader,
|
|
469
|
+
children: [/* @__PURE__ */ t("div", {
|
|
470
|
+
className: Y.sectionLabel,
|
|
471
|
+
children: e
|
|
472
|
+
}), s && /* @__PURE__ */ t("button", {
|
|
473
|
+
type: "button",
|
|
474
|
+
className: Y.allToggle,
|
|
475
|
+
onClick: () => s(m ? [] : r),
|
|
476
|
+
children: m ? "Deselect all" : "Select all"
|
|
477
|
+
})]
|
|
478
|
+
}),
|
|
479
|
+
c && /* @__PURE__ */ t("input", {
|
|
480
|
+
type: "text",
|
|
481
|
+
className: Y.search,
|
|
482
|
+
placeholder: `Search ${e.toLowerCase()}…`,
|
|
483
|
+
autoComplete: "off",
|
|
484
|
+
value: l,
|
|
485
|
+
onClick: (e) => e.stopPropagation(),
|
|
486
|
+
onChange: (e) => u(e.target.value)
|
|
487
|
+
}),
|
|
488
|
+
/* @__PURE__ */ n("div", {
|
|
489
|
+
className: Y.optionsList,
|
|
490
|
+
children: [p.length === 0 && /* @__PURE__ */ t("div", {
|
|
491
|
+
className: Y.empty,
|
|
492
|
+
children: "No match"
|
|
493
|
+
}), p.map((e) => /* @__PURE__ */ n("label", {
|
|
494
|
+
className: Y.option,
|
|
495
|
+
children: [/* @__PURE__ */ t(I, {
|
|
496
|
+
checked: a.has(e),
|
|
497
|
+
onChange: () => o(e)
|
|
498
|
+
}), /* @__PURE__ */ t("span", { children: i(e) })]
|
|
499
|
+
}, e))]
|
|
500
|
+
})
|
|
501
|
+
] });
|
|
502
|
+
}
|
|
503
|
+
var Z = {
|
|
504
|
+
sidebar: "_sidebar_1fx39_1",
|
|
505
|
+
title: "_title_1fx39_16",
|
|
506
|
+
navLink: "_navLink_1fx39_22",
|
|
507
|
+
count: "_count_1fx39_38"
|
|
508
|
+
};
|
|
509
|
+
//#endregion
|
|
510
|
+
//#region src/components/UiElementsSidebar.tsx
|
|
511
|
+
function Q({ sections: e }) {
|
|
512
|
+
return /* @__PURE__ */ n("aside", {
|
|
513
|
+
className: Z.sidebar,
|
|
514
|
+
children: [/* @__PURE__ */ t("div", {
|
|
515
|
+
className: Z.title,
|
|
516
|
+
children: "UI Elements"
|
|
517
|
+
}), e.map((e) => /* @__PURE__ */ n("a", {
|
|
518
|
+
href: `#${e.id}`,
|
|
519
|
+
className: Z.navLink,
|
|
520
|
+
children: [/* @__PURE__ */ t("span", { children: e.label }), /* @__PURE__ */ t("span", {
|
|
521
|
+
className: Z.count,
|
|
522
|
+
children: e.count
|
|
523
|
+
})]
|
|
524
|
+
}, e.id))]
|
|
525
|
+
});
|
|
526
|
+
}
|
|
527
|
+
var $ = {
|
|
528
|
+
line: "_line_q3udz_1",
|
|
529
|
+
box: "_box_q3udz_2",
|
|
530
|
+
tab: "_tab_q3udz_8",
|
|
531
|
+
selected: "_selected_q3udz_52",
|
|
532
|
+
icon: "_icon_q3udz_61"
|
|
533
|
+
};
|
|
534
|
+
//#endregion
|
|
535
|
+
//#region src/components/Tabs.tsx
|
|
536
|
+
function te({ items: e, value: r, onChange: i, variant: a = "line", ...o }) {
|
|
537
|
+
let s = e.filter((e) => !e.disabled).map((e) => e.value);
|
|
538
|
+
function c(e) {
|
|
539
|
+
let t = s.indexOf(r);
|
|
540
|
+
if (t === -1) return;
|
|
541
|
+
let n = null;
|
|
542
|
+
e.key === "ArrowRight" && (n = (t + 1) % s.length), e.key === "ArrowLeft" && (n = (t - 1 + s.length) % s.length), e.key === "Home" && (n = 0), e.key === "End" && (n = s.length - 1), n !== null && (e.preventDefault(), i(s[n]));
|
|
543
|
+
}
|
|
544
|
+
return /* @__PURE__ */ t("div", {
|
|
545
|
+
role: "tablist",
|
|
546
|
+
className: $[a],
|
|
547
|
+
onKeyDown: c,
|
|
548
|
+
...o,
|
|
549
|
+
children: e.map((e) => {
|
|
550
|
+
let a = e.value === r;
|
|
551
|
+
return /* @__PURE__ */ n("button", {
|
|
552
|
+
type: "button",
|
|
553
|
+
role: "tab",
|
|
554
|
+
"aria-selected": a,
|
|
555
|
+
disabled: e.disabled,
|
|
556
|
+
tabIndex: a ? 0 : -1,
|
|
557
|
+
className: [$.tab, a && $.selected].filter(Boolean).join(" "),
|
|
558
|
+
onClick: () => !e.disabled && i(e.value),
|
|
559
|
+
children: [e.icon && /* @__PURE__ */ t("span", {
|
|
560
|
+
className: $.icon,
|
|
561
|
+
children: e.icon
|
|
562
|
+
}), e.label]
|
|
563
|
+
}, e.value);
|
|
564
|
+
})
|
|
565
|
+
});
|
|
566
|
+
}
|
|
567
|
+
//#endregion
|
|
568
|
+
//#region src/utils/format.ts
|
|
569
|
+
function ne(e) {
|
|
570
|
+
let t = Math.floor(e / 60), n = e % 60;
|
|
571
|
+
return `${t}h:${String(n).padStart(2, "0")}m`;
|
|
572
|
+
}
|
|
573
|
+
function re(e, t) {
|
|
574
|
+
let n = Math.floor(e / 60), r = e % 60, i = (e) => String(e).padStart(2, "0");
|
|
575
|
+
return `${i(n)}:${i(r)}:${i(t)}`;
|
|
576
|
+
}
|
|
577
|
+
//#endregion
|
|
578
|
+
export { p as Button, h as Card, I as Checkbox, X as FilterSection, J as HighlightText, H as Menu, U as MenuDivider, G as MenuItem, R as RadioButton, te as Tabs, _ as Tag, B as TextField, P as Toolbar, Q as UiElementsSidebar, ne as formatDuration, re as formatDurationHMS };
|
|
579
|
+
|
|
580
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/components/Button.module.css","../src/components/Button.tsx","../src/components/Card.module.css","../src/components/Card.tsx","../src/components/Tag.module.css","../src/components/Tag.tsx","../node_modules/lucide-react/dist/esm/shared/src/utils/toKebabCase.mjs","../node_modules/lucide-react/dist/esm/shared/src/utils/toLucideIconData.mjs","../node_modules/lucide-react/dist/esm/shared/src/utils/toCamelCase.mjs","../node_modules/lucide-react/dist/esm/shared/src/utils/toPascalCase.mjs","../node_modules/lucide-react/dist/esm/shared/src/utils/mergeClasses.mjs","../node_modules/lucide-react/dist/esm/shared/src/build/defaultAttributes.mjs","../node_modules/lucide-react/dist/esm/shared/src/build/buildLucideIconNode.mjs","../node_modules/lucide-react/dist/esm/shared/src/build/buildLucideIconForReact.mjs","../node_modules/lucide-react/dist/esm/shared/src/utils/hasA11yProp.mjs","../node_modules/lucide-react/dist/esm/context.mjs","../node_modules/lucide-react/dist/esm/Icon.mjs","../node_modules/lucide-react/dist/esm/createLucideIcon.mjs","../node_modules/lucide-react/dist/esm/icons/search.mjs","../src/components/Toolbar.module.css","../src/components/Toolbar.tsx","../src/components/Checkbox.module.css","../src/components/Checkbox.tsx","../src/components/RadioButton.module.css","../src/components/RadioButton.tsx","../src/components/TextField.module.css","../src/components/TextField.tsx","../src/components/Menu.module.css","../src/components/Menu.tsx","../src/components/MenuItem.module.css","../src/components/MenuItem.tsx","../src/components/HighlightText.module.css","../src/components/HighlightText.tsx","../src/components/FilterSection.module.css","../src/components/FilterSection.tsx","../src/components/UiElementsSidebar.module.css","../src/components/UiElementsSidebar.tsx","../src/components/Tabs.module.css","../src/components/Tabs.tsx","../src/utils/format.ts"],"sourcesContent":[".primary,\n.secondary,\n.tertiary,\n.dangerous {\n position: relative;\n isolation: isolate;\n overflow: hidden;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n border: none;\n font-family: inherit;\n font-weight: 450;\n letter-spacing: 0.01em;\n cursor: pointer;\n transition:\n color 0.2s ease,\n transform 0.2s ease-out;\n}\n.primary:active:not(:disabled),\n.secondary:active:not(:disabled),\n.tertiary:active:not(:disabled),\n.dangerous:active:not(:disabled) {\n transform: scale(0.95);\n}\n\n.sm {\n border-radius: 10px;\n padding: 8px 12px;\n font-size: 0.8rem;\n}\n.base {\n border-radius: 12px;\n padding: 12px 16px;\n font-size: 0.9rem;\n}\n.lg {\n border-radius: 14px;\n padding: 16px 22px;\n font-size: 1rem;\n}\n\n.icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n flex-shrink: 0;\n}\n.icon svg {\n width: 100%;\n height: 100%;\n}\n\n.iconOnly {\n aspect-ratio: 1;\n box-sizing: border-box;\n}\n.iconOnly.sm {\n padding: 8px;\n}\n.iconOnly.base {\n padding: 12px;\n}\n.iconOnly.lg {\n padding: 16px;\n}\n.primary::before,\n.secondary::before,\n.tertiary::before,\n.dangerous::before {\n content: '';\n position: absolute;\n left: 50%;\n bottom: 0;\n width: 24%;\n aspect-ratio: 1;\n border-radius: 50%;\n transform: translate(-50%, 100%) scale(1);\n transition: transform 0.3s cubic-bezier(0.39, 0.575, 0.565, 1);\n z-index: -1;\n pointer-events: none;\n}\n.primary:hover::before,\n.secondary:hover::before,\n.tertiary:hover::before,\n.dangerous:hover::before {\n transform: translate(-50%, 15%) scale(8);\n}\n\n.primary {\n background: var(--brand-dark);\n color: #fff;\n font-weight: 400;\n letter-spacing: 0.02em;\n}\n.primary::before {\n background: rgba(255, 255, 255, 0.08);\n}\n.primary:active:not(:disabled)::before {\n background: rgba(0, 0, 0, 0.08);\n}\n\n.secondary {\n background: var(--surface-muted);\n color: var(--text-primary);\n}\n.secondary::before {\n background: rgba(var(--brand-main-rgb), 0.16);\n}\n.secondary:active:not(:disabled)::before {\n background: rgba(var(--brand-main-rgb), 0.28);\n}\n.secondary:hover {\n color: var(--brand-main);\n}\n\n.tertiary {\n background: transparent;\n color: var(--text-secondary);\n}\n.tertiary::before {\n background: rgba(var(--brand-main-rgb), 0.16);\n}\n.tertiary:active:not(:disabled)::before {\n background: rgba(var(--brand-main-rgb), 0.28);\n}\n.tertiary:hover,\n.tertiary:active:not(:disabled) {\n background: var(--bg);\n}\n.tertiary:hover {\n color: var(--brand-main);\n}\n\n.dangerous {\n background: var(--danger-bg);\n color: var(--danger-text-dark);\n}\n.dangerous::before {\n background: rgba(var(--danger-rgb), 0.16);\n}\n.dangerous:active:not(:disabled)::before {\n background: rgba(var(--danger-rgb), 0.28);\n}\n\n.primary:disabled,\n.secondary:disabled,\n.tertiary:disabled,\n.dangerous:disabled {\n background: var(--disabled-bg);\n color: var(--disabled-text);\n cursor: not-allowed;\n}\n.primary:disabled:hover,\n.secondary:disabled:hover,\n.tertiary:disabled:hover,\n.dangerous:disabled:hover {\n color: var(--disabled-text);\n}\n.primary:disabled::before,\n.secondary:disabled::before,\n.tertiary:disabled::before,\n.dangerous:disabled::before {\n display: none;\n}\n","import type { ButtonHTMLAttributes, ReactNode } from 'react';\nimport styles from './Button.module.css';\n\ntype ButtonVariant = 'primary' | 'secondary' | 'tertiary' | 'dangerous';\ntype ButtonSize = 'sm' | 'base' | 'lg';\n\ninterface ButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'className'> {\n variant?: ButtonVariant;\n size?: ButtonSize;\n /** Icon shown before the label. Omit `children` to render an icon-only square button — pass `aria-label` in that case. */\n leadingIcon?: ReactNode;\n /** Icon shown after the label. */\n trailingIcon?: ReactNode;\n children?: ReactNode;\n}\n\nexport function Button({\n variant = 'primary',\n size = 'base',\n leadingIcon,\n trailingIcon,\n children,\n ...rest\n}: ButtonProps) {\n const iconOnly = !children && Boolean(leadingIcon);\n return (\n <button\n type=\"button\"\n className={`${styles[variant]} ${styles[size]}${iconOnly ? ` ${styles.iconOnly}` : ''}`}\n {...rest}\n >\n {leadingIcon && <span className={styles.icon}>{leadingIcon}</span>}\n {children}\n {trailingIcon && <span className={styles.icon}>{trailingIcon}</span>}\n </button>\n );\n}\n",".wrap {\n position: relative;\n width: 220px;\n flex: 0 0 220px;\n}\n.wrap:hover {\n z-index: 10;\n}\n.fluid {\n width: 100%;\n flex: none;\n}\n\n.backing {\n position: absolute;\n left: 6px;\n right: 6px;\n bottom: -4px;\n height: 10px;\n background: var(--card-surface);\n box-shadow: inset 0 0 0 1px var(--border);\n border-radius: 0 0 14px 14px;\n z-index: 0;\n}\n.backing.completed {\n background: var(--success-bg);\n box-shadow: inset 0 0 0 1px #bfe3cc;\n}\n\n.card {\n position: relative;\n z-index: 1;\n width: 100%;\n box-sizing: border-box;\n background: var(--card-surface);\n box-shadow:\n inset 0 0 0 1px #efefef,\n 0 1px 2px rgba(16, 24, 32, 0.04);\n border-radius: 16px;\n padding: 12px 14px;\n cursor: default;\n transition: box-shadow 0.2s;\n}\n.card.interactive {\n cursor: pointer;\n}\n.card.grabbable {\n cursor: grab;\n}\n.card.grabbable:active {\n cursor: grabbing;\n}\n.card.dragging,\n.card.dragging:hover {\n box-shadow:\n inset 0 0 0 1px #efefef,\n 0 1px 2px rgba(16, 24, 32, 0.04);\n}\n.card.interactive:hover {\n box-shadow:\n inset 0 0 0 1px #efefef,\n 0 0 0 2px var(--brand-main);\n}\n.card.completed {\n background: var(--success-bg);\n box-shadow:\n inset 0 0 0 1px #bfe3cc,\n 0 1px 2px rgba(16, 24, 32, 0.04),\n 0 2px 8px rgba(16, 24, 32, 0.06);\n}\n","import type { HTMLAttributes, ReactNode } from 'react';\nimport styles from './Card.module.css';\n\ninterface CardProps extends Omit<HTMLAttributes<HTMLDivElement>, 'className'> {\n /** Shows a second sheet behind the card, for representing a stack/batch. */\n stacked?: boolean;\n /** Success-tinted surface, e.g. a completed task. */\n completed?: boolean;\n /** Adds pointer cursor + accent hover ring. */\n interactive?: boolean;\n /** Grab cursor, for drag sources — pair with `interactive`. */\n draggable?: boolean;\n /** Suppresses the hover ring while a drag is in progress. */\n dragging?: boolean;\n /** Card fills its container width instead of a fixed width. */\n fluid?: boolean;\n children: ReactNode;\n}\n\nexport function Card({\n stacked,\n completed,\n interactive,\n draggable,\n dragging,\n fluid,\n children,\n ...rest\n}: CardProps) {\n return (\n <div className={`${styles.wrap} ${fluid ? styles.fluid : ''}`}>\n {stacked && <div className={`${styles.backing} ${completed ? styles.completed : ''}`} />}\n <div\n className={[\n styles.card,\n completed ? styles.completed : '',\n interactive ? styles.interactive : '',\n draggable ? styles.grabbable : '',\n dragging ? styles.dragging : '',\n ]\n .filter(Boolean)\n .join(' ')}\n {...rest}\n >\n {children}\n </div>\n </div>\n );\n}\n",".neutral,\n.pill,\n.accent,\n.success,\n.danger,\n.count {\n display: inline-flex;\n align-items: center;\n font-weight: 500;\n white-space: nowrap;\n}\n\n/* Square tags — e.g. day badges, worker names, video panel tags */\n.neutral {\n color: var(--text-tertiary);\n font-size: 0.75rem;\n background: var(--bg);\n border-radius: 6px;\n padding: 2px 7px;\n}\n\n/* Pill tags — e.g. BPO group labels, total-duration tags */\n.pill {\n background: var(--card-surface);\n box-shadow: inset 0 0 0 1px var(--border);\n color: var(--text-tertiary);\n font-size: 0.8rem;\n padding: 3px 11px;\n border-radius: 999px;\n}\n\n/* Accent pill — e.g. \"current\" stat, read-only banner badge */\n.accent {\n background: var(--brand-bg);\n color: var(--brand-dark);\n font-size: 0.8rem;\n padding: 3px 11px;\n border-radius: 999px;\n}\n\n/* Success pill — e.g. \"time spent\" stat */\n.success {\n background: var(--success-bg);\n color: var(--success-text);\n font-size: 0.8rem;\n padding: 3px 11px;\n border-radius: 999px;\n}\n\n/* Danger — square (e.g. ASAP tag) reuses the same token pair as the\n pill-shaped status variant; only the shape differs by context. */\n.danger {\n color: var(--danger-text);\n font-size: 0.75rem;\n background: var(--danger-bg);\n border-radius: 6px;\n padding: 2px 7px;\n}\n\n/* Count badge — small solid circle, e.g. active-filter count */\n.count {\n justify-content: center;\n min-width: 16px;\n height: 16px;\n padding: 0 4px;\n border-radius: 999px;\n background: var(--brand-main);\n color: #fff;\n font-size: 0.65rem;\n line-height: 16px;\n text-align: center;\n}\n","import type { HTMLAttributes, ReactNode } from 'react';\nimport styles from './Tag.module.css';\n\ntype TagVariant = 'neutral' | 'pill' | 'accent' | 'success' | 'danger' | 'count';\n\ninterface TagProps extends Omit<HTMLAttributes<HTMLSpanElement>, 'className'> {\n variant?: TagVariant;\n children: ReactNode;\n}\n\nexport function Tag({ variant = 'neutral', children, ...rest }: TagProps) {\n return (\n <span className={styles[variant]} {...rest}>\n {children}\n </span>\n );\n}\n","/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst toKebabCase = (string) => string?.replace(/([a-z0-9])([A-Z])/g, \"$1-$2\").toLowerCase();\n\nexport { toKebabCase };\n//# sourceMappingURL=toKebabCase.mjs.map\n","/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport { toKebabCase } from './toKebabCase.mjs';\n\nfunction toLucideIconData(iconName, iconNode, aliases = []) {\n if (iconNode == null) {\n throw new Error(\"[lucide]: iconNode is required when icon name is used\");\n }\n return {\n name: toKebabCase(iconName),\n size: 24,\n node: iconNode,\n ...aliases.length > 0 ? { aliases } : {}\n };\n}\n\nexport { toLucideIconData };\n//# sourceMappingURL=toLucideIconData.mjs.map\n","/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst toCamelCase = (string) => {\n let out = \"\";\n let upperNext = false;\n for (const ch of string) {\n if (ch === \"-\" || ch === \"_\" || ch <= \" \") {\n upperNext = out.length > 0;\n continue;\n }\n if (out.length === 0) {\n out += ch.toLowerCase();\n } else {\n out += upperNext ? ch.toUpperCase() : ch;\n }\n upperNext = false;\n }\n return out;\n};\n\nexport { toCamelCase };\n//# sourceMappingURL=toCamelCase.mjs.map\n","/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport { toCamelCase } from './toCamelCase.mjs';\n\nconst toPascalCase = (string) => {\n const camelCase = toCamelCase(string);\n return camelCase.charAt(0).toUpperCase() + camelCase.slice(1);\n};\n\nexport { toPascalCase };\n//# sourceMappingURL=toPascalCase.mjs.map\n","/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst mergeClasses = (...classes) => classes.filter((className, index, array) => {\n return Boolean(className) && className.trim() !== \"\" && array.indexOf(className) === index;\n}).join(\" \").trim();\n\nexport { mergeClasses };\n//# sourceMappingURL=mergeClasses.mjs.map\n","/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst defaultAttributes = {\n xmlns: \"http://www.w3.org/2000/svg\",\n width: 24,\n height: 24,\n viewBox: \"0 0 24 24\",\n fill: \"none\",\n stroke: \"currentColor\",\n \"stroke-width\": 2,\n \"stroke-linecap\": \"round\",\n \"stroke-linejoin\": \"round\"\n};\n\nexport { defaultAttributes as default };\n//# sourceMappingURL=defaultAttributes.mjs.map\n","/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport defaultAttributes from './defaultAttributes.mjs';\nimport { mergeClasses } from '../utils/mergeClasses.mjs';\n\nfunction isDefined(value) {\n return value !== null && value !== void 0;\n}\nfunction buildLucideIconNode(icon, params = {}) {\n const attributeNames = params.attributeNames ?? {};\n const getAttributeName = (attributeName) => attributeNames[attributeName] ?? attributeName;\n const viewBoxWidth = icon.size ?? icon.width ?? defaultAttributes[\"width\"];\n const viewBoxHeight = icon.size ?? icon.height ?? defaultAttributes[\"height\"];\n const aliasClassNames = icon.aliases?.filter((alias) => typeof alias === \"string\" && alias.trim() !== \"\").map((alias) => `lucide-${alias}`) ?? [];\n const iconClassNames = [...icon.name ? [`lucide-${icon.name}`] : [], ...aliasClassNames];\n const classNamesFromClassName = params.className?.split(\" \").filter(Boolean) ?? [];\n const className = params.includeDefaultClasses === false ? mergeClasses(...classNamesFromClassName) : mergeClasses(\"lucide\", ...iconClassNames, ...classNamesFromClassName);\n const calculatedStrokeWidth = params.absoluteStrokeWidth ? Number(params.strokeWidth ?? defaultAttributes[\"stroke-width\"]) * Number(icon.size ?? icon.width ?? defaultAttributes[\"width\"]) / Number(params.size ?? params.width ?? defaultAttributes[\"width\"]) : params.strokeWidth ?? defaultAttributes[\"stroke-width\"];\n const attributes = {\n ...Object.entries(defaultAttributes).reduce((attrs, [attrName, value]) => {\n attrs[getAttributeName(attrName)] = value;\n return attrs;\n }, {}),\n ...\"color\" in params && params.color && {\n [getAttributeName(\"stroke\")]: params.color\n },\n ...\"size\" in params && isDefined(params.size) && {\n [getAttributeName(\"width\")]: params.size,\n [getAttributeName(\"height\")]: params.size\n },\n ...\"width\" in params && isDefined(params.width) && {\n [getAttributeName(\"width\")]: params.width\n },\n ...\"height\" in params && isDefined(params.height) && {\n [getAttributeName(\"height\")]: params.height\n },\n [getAttributeName(\"stroke-width\")]: calculatedStrokeWidth,\n ...className && {\n [getAttributeName(\"class\")]: className\n },\n [getAttributeName(\"viewBox\")]: `0 0 ${viewBoxWidth} ${viewBoxHeight}`,\n ...params.hasA11yProp === false ? {\n [getAttributeName(\"aria-hidden\")]: \"true\"\n } : {},\n ...\"attributes\" in params && params.attributes\n };\n return [\n \"svg\",\n attributes,\n icon.node.map((child) => {\n const [name, attrs, children] = child;\n const nextAttrs = params.nonScalingStroke ? { [getAttributeName(\"vector-effect\")]: \"non-scaling-stroke\", ...attrs } : attrs;\n return children ? [name, nextAttrs, children] : [name, nextAttrs];\n })\n ];\n}\n\nexport { buildLucideIconNode as default };\n//# sourceMappingURL=buildLucideIconNode.mjs.map\n","/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport buildLucideIconNode from './buildLucideIconNode.mjs';\n\nfunction buildLucideIconForReact(icon, params = {}) {\n return buildLucideIconNode(icon, {\n ...params,\n attributeNames: {\n ...params.attributeNames,\n class: \"className\",\n \"stroke-width\": \"strokeWidth\",\n \"stroke-linecap\": \"strokeLinecap\",\n \"stroke-linejoin\": \"strokeLinejoin\",\n \"vector-effect\": \"vectorEffect\"\n }\n });\n}\n\nexport { buildLucideIconForReact as default };\n//# sourceMappingURL=buildLucideIconForReact.mjs.map\n","/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst hasA11yProp = (props) => {\n for (const prop in props) {\n if (prop.startsWith(\"aria-\") || prop === \"role\" || prop === \"title\") {\n return true;\n }\n }\n return false;\n};\n\nexport { hasA11yProp };\n//# sourceMappingURL=hasA11yProp.mjs.map\n","\"use strict\";\n\"use client\";\n/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport { createContext, useContext, useMemo, createElement } from 'react';\n\nconst LucideContext = createContext({});\nfunction LucideProvider({\n children,\n size,\n color,\n strokeWidth,\n absoluteStrokeWidth,\n nonScalingStroke,\n className\n}) {\n const value = useMemo(\n () => ({\n size,\n color,\n strokeWidth,\n absoluteStrokeWidth,\n nonScalingStroke,\n className\n }),\n [size, color, strokeWidth, absoluteStrokeWidth, nonScalingStroke, className]\n );\n return createElement(LucideContext.Provider, { value }, children);\n}\nconst useLucideContext = () => useContext(LucideContext);\n\nexport { LucideProvider, useLucideContext };\n//# sourceMappingURL=context.mjs.map\n","\"use strict\";\n\"use client\";\n/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport { forwardRef, createElement } from 'react';\nimport { mergeClasses } from './shared/src/utils/mergeClasses.mjs';\nimport buildLucideIconForReact from './shared/src/build/buildLucideIconForReact.mjs';\nimport { hasA11yProp } from './shared/src/utils/hasA11yProp.mjs';\nimport { useLucideContext } from './context.mjs';\n\nconst Icon = forwardRef(\n ({\n color,\n size,\n width,\n height,\n strokeWidth,\n absoluteStrokeWidth,\n nonScalingStroke,\n className = \"\",\n children,\n iconNode = [],\n icon = {\n node: iconNode,\n aliases: [],\n size: 24\n },\n ...rest\n }, ref) => {\n const {\n size: contextSize = 24,\n strokeWidth: contextStrokeWidth = 2,\n absoluteStrokeWidth: contextAbsoluteStrokeWidth = false,\n nonScalingStroke: contextNonScalingStroke = false,\n color: contextColor = \"currentColor\",\n className: contextClass = \"\"\n } = useLucideContext() ?? {};\n const hasAccessibleProp = Boolean(children) || hasA11yProp(rest);\n const [name, svgAttributes, builtIconNode = []] = buildLucideIconForReact(icon, {\n color: color ?? contextColor,\n width: width ?? size ?? contextSize,\n height: height ?? size ?? contextSize,\n strokeWidth: strokeWidth ?? contextStrokeWidth,\n absoluteStrokeWidth: absoluteStrokeWidth ?? contextAbsoluteStrokeWidth,\n nonScalingStroke: nonScalingStroke ?? contextNonScalingStroke,\n className: mergeClasses(contextClass, className),\n hasA11yProp: hasAccessibleProp,\n attributes: rest\n });\n return createElement(\n name,\n {\n ref,\n ...svgAttributes\n },\n [\n ...builtIconNode.map(([tag, attrs]) => createElement(tag, attrs)),\n ...Array.isArray(children) ? children : [children]\n ]\n );\n }\n);\n\nexport { Icon as default };\n//# sourceMappingURL=Icon.mjs.map\n","/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport { forwardRef, createElement } from 'react';\nimport { toLucideIconData } from './shared/src/utils/toLucideIconData.mjs';\nimport { toPascalCase } from './shared/src/utils/toPascalCase.mjs';\nimport Icon from './Icon.mjs';\n\nfunction createLucideIcon(iconDataOrName, iconNode = [], aliases = []) {\n const iconData = typeof iconDataOrName === \"string\" ? toLucideIconData(iconDataOrName, iconNode, aliases) : iconDataOrName;\n const Component = forwardRef(\n ({ className, ...props }, ref) => createElement(Icon, {\n ref,\n icon: iconData,\n className,\n ...props\n })\n );\n if (iconData.name) {\n Component.displayName = toPascalCase(iconData.name);\n }\n return Component;\n}\n\nexport { createLucideIcon as default };\n//# sourceMappingURL=createLucideIcon.mjs.map\n","/**\n * @license lucide-react v1.46.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconData = {\n name: \"search\",\n size: 24,\n node: [\n [\"path\", { d: \"m21 21-4.34-4.34\", key: \"14j7rj\" }],\n [\"circle\", { cx: \"11\", cy: \"11\", r: \"8\", key: \"4ej97u\" }]\n ]\n};\n__iconData.node;\nconst Search = createLucideIcon(__iconData);\n\nexport { __iconData, Search as default };\n//# sourceMappingURL=search.mjs.map\n",".toolbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 16px;\n padding: 0 8px;\n background: var(--card-surface);\n border-radius: 16px;\n box-shadow:\n inset 0 0 0 1px var(--border),\n 0 1px 2px rgba(16, 24, 32, 0.04),\n 0 2px 8px rgba(16, 24, 32, 0.06);\n}\n.searchWrap {\n position: relative;\n flex: 1;\n min-width: 0;\n}\n.searchWrap::after {\n content: '';\n position: absolute;\n left: 36px;\n right: 0;\n bottom: 0;\n height: 2px;\n background: var(--brand-main);\n opacity: 0;\n pointer-events: none;\n}\n.searchWrap:focus-within::after {\n opacity: 1;\n}\n.searchIcon {\n position: absolute;\n top: 50%;\n left: 12px;\n width: 16px;\n height: 16px;\n transform: translateY(-53%);\n color: var(--text-tertiary);\n pointer-events: none;\n}\n.searchIcon svg {\n width: 100%;\n height: 100%;\n}\n.search {\n width: 100%;\n box-sizing: border-box;\n border: none;\n padding: 16px 52px 16px 36px;\n font-family: inherit;\n font-size: 1rem;\n color: var(--text-primary);\n background: none;\n box-shadow: inset -1px 0 0 var(--border);\n}\n.search:focus {\n outline: none;\n}\n.searchShortcut {\n position: absolute;\n top: 50%;\n right: 8px;\n transform: translateY(-50%);\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 2px 6px;\n border-radius: 6px;\n background: var(--bg);\n color: var(--text-tertiary);\n font-size: 0.75rem;\n font-weight: 600;\n letter-spacing: 0.02em;\n pointer-events: none;\n}\n.controls {\n display: flex;\n align-items: center;\n flex: none;\n}\n","import { useEffect, useRef, type ChangeEvent, type ReactNode } from 'react';\nimport { Search } from 'lucide-react';\nimport styles from './Toolbar.module.css';\n\ninterface ToolbarProps {\n searchValue?: string;\n onSearchChange?: (value: string) => void;\n placeholder?: string;\n /** Text shown in the keyboard-shortcut badge, e.g. \"⌘K\". Omit to hide the badge. */\n shortcutLabel?: string;\n /** Focuses the search input when Cmd/Ctrl + the shortcut key is pressed. */\n shortcutKey?: string;\n /** Right-side content — filter/sort controls, actions, etc. */\n children?: ReactNode;\n}\n\nexport function Toolbar({\n searchValue,\n onSearchChange,\n placeholder = 'Search…',\n shortcutLabel = '⌘K',\n shortcutKey = 'k',\n children,\n}: ToolbarProps) {\n const searchRef = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n function onKeyDown(e: KeyboardEvent) {\n if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === shortcutKey.toLowerCase()) {\n e.preventDefault();\n searchRef.current?.focus();\n }\n }\n window.addEventListener('keydown', onKeyDown);\n return () => window.removeEventListener('keydown', onKeyDown);\n }, [shortcutKey]);\n\n return (\n <div className={styles.toolbar}>\n <div className={styles.searchWrap}>\n <span className={styles.searchIcon}>\n <Search />\n </span>\n <input\n ref={searchRef}\n type=\"text\"\n className={styles.search}\n placeholder={placeholder}\n autoComplete=\"off\"\n value={searchValue}\n onChange={(e: ChangeEvent<HTMLInputElement>) => onSearchChange?.(e.target.value)}\n />\n {shortcutLabel && (\n <span className={styles.searchShortcut} aria-hidden=\"true\">\n {shortcutLabel}\n </span>\n )}\n </div>\n {children && <div className={styles.controls}>{children}</div>}\n </div>\n );\n}\n",".checkbox {\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n flex-shrink: 0;\n cursor: pointer;\n}\n.input {\n position: absolute;\n inset: 0;\n margin: 0;\n opacity: 0;\n cursor: pointer;\n}\n.box {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n border-radius: 6px;\n background: var(--surface-sunken);\n box-shadow: inset 0 0 0 1px var(--border);\n transition:\n background-color 0.2s cubic-bezier(0, 0, 0.2, 1),\n box-shadow 0.2s cubic-bezier(0, 0, 0.2, 1),\n transform 0.1s cubic-bezier(0, 0, 0.2, 1);\n}\n.input:hover + .box {\n box-shadow: inset 0 0 0 1px var(--brand-main);\n}\n.input:focus-visible + .box {\n outline: 2px solid var(--brand-main);\n outline-offset: 2px;\n}\n.input:active + .box {\n transform: scale(0.88);\n}\n.input:checked + .box {\n background: var(--brand-main);\n box-shadow: inset 0 0 0 1px var(--brand-main);\n}\n.icon {\n width: 10px;\n height: 10px;\n overflow: visible;\n}\n.icon polyline {\n fill: none;\n stroke: #fff;\n stroke-width: 2.5px;\n stroke-linecap: round;\n stroke-linejoin: round;\n stroke-dasharray: 22px;\n stroke-dashoffset: 22px;\n transition: stroke-dashoffset 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n.input:checked + .box .icon polyline {\n stroke-dashoffset: 0px;\n}\n","import type { ChangeEvent } from 'react';\nimport styles from './Checkbox.module.css';\n\ninterface CheckboxProps {\n checked: boolean;\n onChange: (e: ChangeEvent<HTMLInputElement>) => void;\n ariaLabel?: string;\n className?: string;\n}\n\nexport function Checkbox({ checked, onChange, ariaLabel, className }: CheckboxProps) {\n return (\n <label className={`${styles.checkbox} ${className ?? ''}`}>\n <input\n type=\"checkbox\"\n className={styles.input}\n checked={checked}\n onChange={onChange}\n aria-label={ariaLabel}\n />\n <span className={styles.box}>\n <svg className={styles.icon} viewBox=\"0 0 17 18\" aria-hidden=\"true\">\n <polyline points=\"1 9 7 14 15 4\" />\n </svg>\n </span>\n </label>\n );\n}\n",".radio {\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n flex-shrink: 0;\n cursor: pointer;\n}\n.input {\n position: absolute;\n inset: 0;\n margin: 0;\n opacity: 0;\n cursor: pointer;\n}\n.circle {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n border-radius: 50%;\n background: var(--surface-sunken);\n box-shadow: inset 0 0 0 1px var(--border);\n transition:\n background-color 0.2s cubic-bezier(0, 0, 0.2, 1),\n box-shadow 0.2s cubic-bezier(0, 0, 0.2, 1),\n transform 0.1s cubic-bezier(0, 0, 0.2, 1);\n}\n.input:hover + .circle {\n box-shadow: inset 0 0 0 1px var(--brand-main);\n}\n.input:focus-visible + .circle {\n outline: 2px solid var(--brand-main);\n outline-offset: 2px;\n}\n.input:active + .circle {\n transform: scale(0.88);\n}\n.input:checked + .circle {\n background: var(--brand-main);\n box-shadow: inset 0 0 0 1px var(--brand-main);\n}\n.dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: #fff;\n transform: scale(0);\n transition: transform 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n.input:checked + .circle .dot {\n transform: scale(1);\n}\n","import type { ChangeEvent } from 'react';\nimport styles from './RadioButton.module.css';\n\ninterface RadioButtonProps {\n checked: boolean;\n onChange: (e: ChangeEvent<HTMLInputElement>) => void;\n name?: string;\n value?: string;\n ariaLabel?: string;\n className?: string;\n}\n\nexport function RadioButton({ checked, onChange, name, value, ariaLabel, className }: RadioButtonProps) {\n return (\n <label className={`${styles.radio} ${className ?? ''}`}>\n <input\n type=\"radio\"\n className={styles.input}\n checked={checked}\n onChange={onChange}\n name={name}\n value={value}\n aria-label={ariaLabel}\n />\n <span className={styles.circle}>\n <span className={styles.dot} />\n </span>\n </label>\n );\n}\n",".field {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n.label {\n font-size: 0.85rem;\n font-weight: 550;\n color: var(--text-primary);\n padding-left: 8px;\n}\n.inputWrap {\n position: relative;\n display: flex;\n align-items: center;\n background: var(--card-surface);\n box-shadow: inset 0 0 0 1px var(--border-input);\n transition: box-shadow 0.2s ease-out;\n}\n.inputWrap:focus-within {\n box-shadow:\n inset 0 0 0 0 var(--border-input),\n 0 0 0 2px var(--brand-main);\n}\n.errorWrap,\n.errorWrap:focus-within {\n box-shadow: inset 0 0 0 1px var(--danger-text);\n}\n.inputWrap:has(.input:disabled) {\n background: var(--surface-muted);\n}\n\n.sm {\n border-radius: 10px;\n}\n.sm .input {\n padding: 8px 12px;\n font-size: 0.8rem;\n}\n.base {\n border-radius: 12px;\n}\n.base .input {\n padding: 12px 14px;\n font-size: 0.9rem;\n}\n.lg {\n border-radius: 14px;\n}\n.lg .input {\n padding: 16px 16px;\n font-size: 1rem;\n}\n.inputWrap:has(.icon) .input {\n padding-left: 8px;\n}\n\n.icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n margin-left: 12px;\n color: var(--text-tertiary);\n flex-shrink: 0;\n}\n.icon svg {\n width: 100%;\n height: 100%;\n}\n.input {\n flex: 1;\n min-width: 0;\n box-sizing: border-box;\n border: none;\n background: none;\n font-family: inherit;\n color: var(--text-primary);\n font-weight: 450;\n}\n.input:focus {\n outline: none;\n}\n.input::placeholder {\n color: var(--text-tertiary);\n}\n.input:disabled {\n color: var(--disabled-text);\n cursor: not-allowed;\n}\n.helperText {\n font-size: 0.78rem;\n color: var(--text-tertiary);\n padding-left: 8px;\n}\n.errorText {\n font-size: 0.78rem;\n color: var(--danger-text);\n}\n","import { useId, type InputHTMLAttributes, type ReactNode } from 'react';\nimport styles from './TextField.module.css';\n\ntype TextFieldSize = 'sm' | 'base' | 'lg';\n\ninterface TextFieldProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'className' | 'size'> {\n label?: string;\n helperText?: string;\n error?: string;\n size?: TextFieldSize;\n leadingIcon?: ReactNode;\n}\n\nexport function TextField({\n label,\n helperText,\n error,\n size = 'base',\n leadingIcon,\n id,\n ...rest\n}: TextFieldProps) {\n const generatedId = useId();\n const inputId = id ?? generatedId;\n\n return (\n <div className={styles.field}>\n {label && (\n <label className={styles.label} htmlFor={inputId}>\n {label}\n </label>\n )}\n <div className={`${styles.inputWrap} ${styles[size]} ${error ? styles.errorWrap : ''}`}>\n {leadingIcon && <span className={styles.icon}>{leadingIcon}</span>}\n <input id={inputId} className={styles.input} {...rest} />\n </div>\n {error ? (\n <span className={styles.errorText}>{error}</span>\n ) : helperText ? (\n <span className={styles.helperText}>{helperText}</span>\n ) : null}\n </div>\n );\n}\n",".menu {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 180px;\n width: fit-content;\n padding: 4px;\n box-sizing: border-box;\n background: var(--card-surface);\n border-radius: 12px;\n box-shadow:\n inset 0 0 0 1px var(--border),\n 0 8px 24px rgba(0, 0, 0, 0.12);\n}\n.divider {\n height: 1px;\n background: var(--border);\n margin: 4px 6px;\n}\n","import type { HTMLAttributes, ReactNode } from 'react';\nimport styles from './Menu.module.css';\n\ninterface MenuProps extends Omit<HTMLAttributes<HTMLDivElement>, 'className'> {\n children: ReactNode;\n}\n\nexport function Menu({ children, ...rest }: MenuProps) {\n return (\n <div role=\"menu\" className={styles.menu} {...rest}>\n {children}\n </div>\n );\n}\n\nexport function MenuDivider() {\n return <div className={styles.divider} role=\"separator\" />;\n}\n",".item {\n display: flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n box-sizing: border-box;\n border: none;\n background: none;\n border-radius: 8px;\n padding: 8px 10px;\n font-family: inherit;\n font-size: 0.9rem;\n color: var(--text-primary);\n text-align: left;\n cursor: pointer;\n transition:\n background 0.15s ease-out,\n color 0.15s ease-out;\n}\n.item:hover:not(:disabled) {\n background: var(--bg);\n}\n.item:active:not(:disabled) {\n background: var(--brand-bg);\n}\n.item:focus-visible {\n outline: 2px solid var(--brand-main);\n outline-offset: -2px;\n}\n.item:disabled {\n color: var(--disabled-text);\n cursor: not-allowed;\n}\n.icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n color: var(--text-tertiary);\n flex-shrink: 0;\n}\n.icon svg {\n width: 100%;\n height: 100%;\n}\n.label {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.trailing {\n color: var(--text-tertiary);\n font-size: 0.8rem;\n flex-shrink: 0;\n}\n.selected {\n background: var(--brand-bg);\n color: var(--brand-dark);\n}\n.selected .icon {\n color: var(--brand-dark);\n}\n.destructive {\n color: var(--danger-text);\n}\n.destructive .icon {\n color: var(--danger-text);\n}\n.destructive:hover:not(:disabled) {\n background: var(--danger-bg);\n}\n","import type { ButtonHTMLAttributes, ReactNode } from 'react';\nimport styles from './MenuItem.module.css';\n\ninterface MenuItemProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'className'> {\n icon?: ReactNode;\n trailing?: ReactNode;\n selected?: boolean;\n destructive?: boolean;\n children: ReactNode;\n}\n\nexport function MenuItem({ icon, trailing, selected, destructive, children, ...rest }: MenuItemProps) {\n const classes = [styles.item, selected && styles.selected, destructive && styles.destructive]\n .filter(Boolean)\n .join(' ');\n\n return (\n <button type=\"button\" role=\"menuitem\" className={classes} {...rest}>\n {icon && <span className={styles.icon}>{icon}</span>}\n <span className={styles.label}>{children}</span>\n {trailing && <span className={styles.trailing}>{trailing}</span>}\n </button>\n );\n}\n",".highlight {\n background: var(--brand-bg);\n color: var(--brand-dark);\n border-radius: 3px;\n padding: 0 1px;\n}\n","import { Fragment } from 'react';\nimport styles from './HighlightText.module.css';\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nexport function HighlightText({ text, query }: { text: string; query: string }) {\n if (!query) return <>{text}</>;\n\n const parts = text.split(new RegExp(`(${escapeRegExp(query)})`, 'ig'));\n return (\n <>\n {parts.map((part, i) =>\n part.toLowerCase() === query.toLowerCase() ? (\n <mark key={i} className={styles.highlight}>\n {part}\n </mark>\n ) : (\n <Fragment key={i}>{part}</Fragment>\n ),\n )}\n </>\n );\n}\n",".group {\n position: relative;\n}\n.btn {\n display: flex;\n align-items: center;\n gap: 6px;\n background: none;\n border: none;\n border-radius: 12px;\n padding: 12px;\n font-family: inherit;\n font-size: 1rem;\n color: var(--text-primary);\n cursor: pointer;\n transition:\n background 0.2s ease-out,\n box-shadow 0.2s ease-out,\n transform 0.2s ease-out;\n}\n.btn:hover {\n background: rgba(10, 10, 11, 0.04);\n}\n.btn:active {\n background: var(--brand-bg);\n box-shadow: inset 0 2px 1px 0 rgba(0, 140, 216, 0.25);\n transform: scale(0.95);\n}\n.caret {\n color: var(--text-tertiary);\n display: flex;\n align-items: center;\n}\n.caret svg {\n width: 14px;\n height: 14px;\n}\n.label {\n color: var(--text-secondary);\n}\n.badge {\n position: absolute;\n top: 2px;\n right: 2px;\n min-width: 16px;\n height: 16px;\n padding: 0 4px;\n border-radius: 999px;\n background: var(--brand-main, #0a84d8);\n color: #fff;\n font-size: 0.65rem;\n font-weight: 600;\n line-height: 16px;\n text-align: center;\n}\n.value {\n color: var(--text-primary);\n font-weight: 500;\n}\n.panel {\n display: none;\n position: absolute;\n top: calc(100% + 6px);\n left: 0;\n background: #fff;\n border-radius: 12px;\n min-width: 220px;\n width: fit-content;\n max-height: 280px;\n overflow-y: auto;\n box-shadow:\n inset 0 0 0 1px var(--border),\n 0 8px 24px rgba(0, 0, 0, 0.12);\n z-index: 50;\n}\n.panel.open {\n display: block;\n}\n.panelRight {\n left: auto;\n right: 0;\n}\n.panelWide {\n min-width: 260px;\n padding-bottom: 4px;\n}\n.sectionHeader {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n padding: 12px 14px 4px;\n}\n.sectionLabel {\n font-size: 0.75rem;\n font-weight: 600;\n color: var(--text-tertiary);\n text-transform: uppercase;\n letter-spacing: 0.02em;\n}\n.allToggle {\n background: none;\n border: none;\n padding: 0;\n font-family: inherit;\n font-size: 0.75rem;\n font-weight: 600;\n color: var(--brand-main, #0a84d8);\n cursor: pointer;\n}\n.allToggle:hover {\n text-decoration: underline;\n}\n.divider {\n height: 1px;\n background: var(--border);\n margin: 4px 0;\n}\n.option {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px;\n border-radius: 8px;\n font-size: 1rem;\n cursor: pointer;\n}\n.option:hover {\n background: var(--bg);\n}\n.search {\n width: calc(100% - 16px);\n box-sizing: border-box;\n border: none;\n box-shadow: inset 0 0 0 1px var(--border-input);\n border-radius: 8px;\n padding: 8px 12px;\n margin: 8px;\n font-family: inherit;\n font-size: 1rem;\n margin-bottom: 0;\n}\n.search:focus {\n outline: none;\n box-shadow: inset 0 0 0 1px var(--brand-main);\n}\n.optionsList {\n padding: 4px 4px;\n}\n.empty {\n padding: 7px 8px;\n color: var(--text-tertiary);\n font-size: 0.85rem;\n}\n","import { useState } from 'react';\nimport { Checkbox } from './Checkbox';\nimport styles from './FilterSection.module.css';\n\ninterface FilterSectionProps<T extends string> {\n label: string;\n options: T[];\n optionLabel: (opt: T) => string;\n activeSet: Set<T>;\n onToggle: (opt: T) => void;\n onSetAll?: (opts: T[]) => void;\n searchable?: boolean;\n}\n\nexport function FilterSection<T extends string>({\n label,\n options,\n optionLabel,\n activeSet,\n onToggle,\n onSetAll,\n searchable,\n}: FilterSectionProps<T>) {\n const [query, setQuery] = useState('');\n\n const q = query.trim().toLowerCase();\n const matches = q ? options.filter((opt) => optionLabel(opt).toLowerCase().includes(q)) : options;\n const allSelected = options.length > 0 && activeSet.size === options.length;\n\n return (\n <div>\n <div className={styles.sectionHeader}>\n <div className={styles.sectionLabel}>{label}</div>\n {onSetAll && (\n <button\n type=\"button\"\n className={styles.allToggle}\n onClick={() => onSetAll(allSelected ? [] : options)}\n >\n {allSelected ? 'Deselect all' : 'Select all'}\n </button>\n )}\n </div>\n {searchable && (\n <input\n type=\"text\"\n className={styles.search}\n placeholder={`Search ${label.toLowerCase()}…`}\n autoComplete=\"off\"\n value={query}\n onClick={(e) => e.stopPropagation()}\n onChange={(e) => setQuery(e.target.value)}\n />\n )}\n <div className={styles.optionsList}>\n {matches.length === 0 && <div className={styles.empty}>No match</div>}\n {matches.map((opt) => (\n <label key={opt} className={styles.option}>\n <Checkbox checked={activeSet.has(opt)} onChange={() => onToggle(opt)} />\n <span>{optionLabel(opt)}</span>\n </label>\n ))}\n </div>\n </div>\n );\n}\n",".sidebar {\n width: 256px;\n flex: 0 0 256px;\n border-radius: 16px 16px 0 0;\n box-shadow:\n 1px 0 0 rgba(10, 10, 11, 0.03),\n 0 -1px 0 rgba(10, 10, 11, 0.05);\n background: var(--surface-sunken);\n padding: 24px 16px 24px 24px;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n gap: 4px;\n overflow-y: auto;\n}\n.title {\n font-weight: 500;\n font-size: 1.15rem;\n letter-spacing: -0.01em;\n margin: 0 0 16px 8px;\n}\n.navLink {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n padding: 8px 8px;\n border-radius: 8px;\n color: var(--text-secondary);\n text-decoration: none;\n font-size: 0.9rem;\n font-weight: 500;\n}\n.navLink:hover {\n background: var(--card-surface);\n color: var(--text-primary);\n}\n.count {\n color: var(--text-tertiary);\n font-size: 0.78rem;\n font-weight: 500;\n}\n","import styles from './UiElementsSidebar.module.css';\n\ninterface UiElementsSidebarProps {\n sections: { id: string; label: string; count: number }[];\n}\n\nexport function UiElementsSidebar({ sections }: UiElementsSidebarProps) {\n return (\n <aside className={styles.sidebar}>\n <div className={styles.title}>UI Elements</div>\n {sections.map((section) => (\n <a key={section.id} href={`#${section.id}`} className={styles.navLink}>\n <span>{section.label}</span>\n <span className={styles.count}>{section.count}</span>\n </a>\n ))}\n </aside>\n );\n}\n",".line,\n.box {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n}\n\n.tab {\n position: relative;\n isolation: isolate;\n overflow: hidden;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n border: none;\n font-family: inherit;\n font-weight: 450;\n cursor: pointer;\n white-space: nowrap;\n transition: color 0.15s ease-out, background 0.15s ease-out, box-shadow 0.15s ease-out;\n}\n\n.tab::before {\n content: '';\n position: absolute;\n left: 50%;\n bottom: 0;\n width: 40%;\n aspect-ratio: 1;\n border-radius: 50%;\n transform: translate(-50%, 100%) scale(1);\n transition: transform 0.3s cubic-bezier(0.39, 0.575, 0.565, 1);\n z-index: -1;\n pointer-events: none;\n background: rgba(var(--brand-main-rgb), 0.16);\n}\n.tab:hover:not(:disabled)::before {\n transform: translate(-50%, 15%) scale(4);\n}\n.tab:active:not(:disabled)::before {\n background: rgba(var(--brand-main-rgb), 0.28);\n}\n\n.tab:disabled {\n color: var(--disabled-text);\n cursor: not-allowed;\n}\n.tab:disabled::before {\n display: none;\n}\n\n.tab.selected:hover::before {\n display: none;\n}\n\n.tab:focus-visible {\n outline: 2px solid var(--brand-main);\n outline-offset: 2px;\n}\n\n.icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n flex-shrink: 0;\n}\n.icon svg {\n width: 100%;\n height: 100%;\n}\n\n/* Line variant */\n\n.line {\n box-shadow: inset 0 -1px 0 0 var(--border);\n}\n\n.line .tab {\n background: transparent;\n padding: 10px 4px;\n font-size: 0.9rem;\n color: var(--text-secondary);\n box-shadow: inset 0 -2px 0 0 transparent;\n}\n.line .tab:hover:not(:disabled) {\n color: var(--brand-main);\n}\n.line .tab.selected {\n color: var(--text-primary);\n box-shadow: inset 0 -2px 0 0 var(--brand-main);\n}\n\n/* Box variant */\n\n.box {\n background: rgba(16, 24, 32, 0.04);\n border-radius: 10px;\n padding: 4px;\n gap: 4px;\n}\n\n.box .tab {\n border-radius: 8px;\n padding: 8px 14px;\n font-size: 0.9rem;\n background: transparent;\n color: var(--text-secondary);\n}\n.box .tab:hover:not(:disabled) {\n color: var(--brand-main);\n /* box-shadow: 0 0 0px 1px var(--brand-main-30); */\n}\n.box .tab.selected {\n background: var(--card-surface);\n color: var(--text-primary);\n box-shadow: 0 0 1px 0.5px var(--border);\n font-weight: 500;\n}\n","import type { KeyboardEvent, ReactNode } from 'react';\nimport styles from './Tabs.module.css';\n\ntype TabsVariant = 'line' | 'box';\n\ninterface TabItem {\n value: string;\n label: ReactNode;\n icon?: ReactNode;\n disabled?: boolean;\n}\n\ninterface TabsProps {\n items: TabItem[];\n value: string;\n onChange: (value: string) => void;\n variant?: TabsVariant;\n 'aria-label'?: string;\n}\n\nexport function Tabs({ items, value, onChange, variant = 'line', ...rest }: TabsProps) {\n const enabledValues = items.filter((item) => !item.disabled).map((item) => item.value);\n\n function handleKeyDown(event: KeyboardEvent<HTMLDivElement>) {\n const currentIndex = enabledValues.indexOf(value);\n if (currentIndex === -1) return;\n\n let nextIndex: number | null = null;\n if (event.key === 'ArrowRight') nextIndex = (currentIndex + 1) % enabledValues.length;\n if (event.key === 'ArrowLeft') {\n nextIndex = (currentIndex - 1 + enabledValues.length) % enabledValues.length;\n }\n if (event.key === 'Home') nextIndex = 0;\n if (event.key === 'End') nextIndex = enabledValues.length - 1;\n\n if (nextIndex !== null) {\n event.preventDefault();\n onChange(enabledValues[nextIndex]);\n }\n }\n\n return (\n <div role=\"tablist\" className={styles[variant]} onKeyDown={handleKeyDown} {...rest}>\n {items.map((item) => {\n const selected = item.value === value;\n return (\n <button\n key={item.value}\n type=\"button\"\n role=\"tab\"\n aria-selected={selected}\n disabled={item.disabled}\n tabIndex={selected ? 0 : -1}\n className={[styles.tab, selected && styles.selected].filter(Boolean).join(' ')}\n onClick={() => !item.disabled && onChange(item.value)}\n >\n {item.icon && <span className={styles.icon}>{item.icon}</span>}\n {item.label}\n </button>\n );\n })}\n </div>\n );\n}\n","export function formatDuration(mins: number): string {\n const h = Math.floor(mins / 60);\n const m = mins % 60;\n return `${h}h:${String(m).padStart(2, '0')}m`;\n}\n\n/** HH:MM:SS — seconds are a stable per-video display detail, not tracked in the data model. */\nexport function formatDurationHMS(mins: number, seconds: number): string {\n const h = Math.floor(mins / 60);\n const m = mins % 60;\n const pad = (n: number) => String(n).padStart(2, '0');\n return `${pad(h)}:${pad(m)}:${pad(seconds)}`;\n}\n"],"x_google_ignoreList":[6,7,8,9,10,11,12,13,14,15,16,17,18],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "cattle-care-ui",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./style.css": "./dist/index.css",
|
|
14
|
+
"./package.json": "./package.json"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
19
|
+
"sideEffects": [
|
|
20
|
+
"**/*.css"
|
|
21
|
+
],
|
|
22
|
+
"engines": {
|
|
23
|
+
"node": ">=18"
|
|
24
|
+
},
|
|
25
|
+
"scripts": {
|
|
26
|
+
"typecheck": "tsc -b",
|
|
27
|
+
"lint": "oxlint",
|
|
28
|
+
"storybook": "storybook dev -p 6006",
|
|
29
|
+
"build-storybook": "storybook build",
|
|
30
|
+
"build": "tsc -b tsconfig.lib.json && vite build --config vite.config.lib.ts",
|
|
31
|
+
"chromatic": "chromatic --exit-zero-on-changes"
|
|
32
|
+
},
|
|
33
|
+
"peerDependencies": {
|
|
34
|
+
"react": "^19.0.0",
|
|
35
|
+
"react-dom": "^19.0.0"
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"lucide-react": "^1.46.0"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@chromatic-com/storybook": "latest",
|
|
42
|
+
"@storybook/addon-a11y": "^10.6.0",
|
|
43
|
+
"@storybook/addon-docs": "^10.6.0",
|
|
44
|
+
"@storybook/addon-mcp": "^10.6.0",
|
|
45
|
+
"@storybook/addon-vitest": "^10.6.0",
|
|
46
|
+
"@storybook/react-vite": "^10.6.0",
|
|
47
|
+
"@types/node": "^24.13.3",
|
|
48
|
+
"@types/react": "^19.2.18",
|
|
49
|
+
"@types/react-dom": "^19.2.7",
|
|
50
|
+
"@vitejs/plugin-react": "^6.1.1",
|
|
51
|
+
"@vitest/browser-playwright": "latest",
|
|
52
|
+
"@vitest/coverage-v8": "latest",
|
|
53
|
+
"chromatic": "^18.8.0",
|
|
54
|
+
"oxlint": "^1.81.0",
|
|
55
|
+
"playwright": "latest",
|
|
56
|
+
"react": "^19.2.8",
|
|
57
|
+
"react-dom": "^19.2.8",
|
|
58
|
+
"storybook": "^10.6.0",
|
|
59
|
+
"typescript": "~6.0.2",
|
|
60
|
+
"vite": "^8.3.0",
|
|
61
|
+
"vite-plugin-dts": "^5.1.0",
|
|
62
|
+
"vitest": "latest"
|
|
63
|
+
}
|
|
64
|
+
}
|