@lt-three/love3 0.0.0 → 0.1.1
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 +85 -1
- package/dist/native/analytics/animation.d.ts +4 -0
- package/dist/native/analytics/animation.js +6 -0
- package/dist/native/analytics/chart.types.d.ts +25 -0
- package/dist/native/analytics/chart.types.js +0 -0
- package/dist/native/analytics/line-chart.d.ts +4 -0
- package/dist/native/analytics/line-chart.ios.d.ts +4 -0
- package/dist/native/analytics/line-chart.ios.js +24 -0
- package/dist/native/analytics/line-chart.js +33 -0
- package/dist/native/analytics/metric-card.d.ts +10 -0
- package/dist/native/analytics/metric-card.js +29 -0
- package/dist/native/analytics/multi-line-chart.d.ts +18 -0
- package/dist/native/analytics/multi-line-chart.js +216 -0
- package/dist/native/analytics/pie-chart.d.ts +15 -0
- package/dist/native/analytics/pie-chart.ios.d.ts +4 -0
- package/dist/native/analytics/pie-chart.ios.js +24 -0
- package/dist/native/analytics/pie-chart.js +92 -0
- package/dist/native/analytics/single-number.d.ts +19 -0
- package/dist/native/analytics/single-number.js +101 -0
- package/dist/native/atom/avatar.d.ts +21 -0
- package/dist/native/atom/avatar.js +46 -0
- package/dist/native/atom/badge.d.ts +28 -0
- package/dist/native/atom/badge.js +51 -0
- package/dist/native/atom/button.d.ts +46 -0
- package/dist/native/atom/button.js +109 -0
- package/dist/native/atom/checkbox.d.ts +21 -0
- package/dist/native/atom/checkbox.js +47 -0
- package/dist/native/atom/colored-value.d.ts +12 -0
- package/dist/native/atom/colored-value.js +24 -0
- package/dist/native/atom/image.d.ts +21 -0
- package/dist/native/atom/image.js +72 -0
- package/dist/native/atom/label.d.ts +18 -0
- package/dist/native/atom/label.js +33 -0
- package/dist/native/atom/link.d.ts +18 -0
- package/dist/native/atom/link.js +25 -0
- package/dist/native/atom/readout.d.ts +22 -0
- package/dist/native/atom/readout.js +39 -0
- package/dist/native/atom/search-input.d.ts +12 -0
- package/dist/native/atom/search-input.js +36 -0
- package/dist/native/atom/select.d.ts +54 -0
- package/dist/native/atom/select.js +200 -0
- package/dist/native/atom/separator.d.ts +12 -0
- package/dist/native/atom/separator.js +16 -0
- package/dist/native/atom/skeleton.d.ts +12 -0
- package/dist/native/atom/skeleton.js +39 -0
- package/dist/native/atom/slider.d.ts +32 -0
- package/dist/native/atom/slider.js +75 -0
- package/dist/native/atom/spinner.d.ts +15 -0
- package/dist/native/atom/spinner.js +25 -0
- package/dist/native/atom/switch.d.ts +18 -0
- package/dist/native/atom/switch.js +52 -0
- package/dist/native/atom/symbol.d.ts +16 -0
- package/dist/native/atom/symbol.js +38 -0
- package/dist/native/atom/symbol.types.d.ts +25 -0
- package/dist/native/atom/symbol.types.js +49 -0
- package/dist/native/atom/text-field.d.ts +49 -0
- package/dist/native/atom/text-field.js +56 -0
- package/dist/native/atom/text.d.ts +2 -0
- package/dist/native/atom/text.js +3 -0
- package/dist/native/atom/theme-toggle.d.ts +21 -0
- package/dist/native/atom/theme-toggle.js +36 -0
- package/dist/native/atom/timezone-select.d.ts +16 -0
- package/dist/native/atom/timezone-select.js +28 -0
- package/dist/native/atom/typography.d.ts +13 -0
- package/dist/native/atom/typography.js +28 -0
- package/dist/native/base/button.d.ts +61 -0
- package/dist/native/base/button.js +92 -0
- package/dist/native/base/form.d.ts +72 -0
- package/dist/native/base/form.js +113 -0
- package/dist/native/base/glass-card.d.ts +15 -0
- package/dist/native/base/glass-card.js +38 -0
- package/dist/native/base/input.d.ts +29 -0
- package/dist/native/base/input.js +27 -0
- package/dist/native/base/sheet.d.ts +71 -0
- package/dist/native/base/sheet.js +187 -0
- package/dist/native/base/text.d.ts +14 -0
- package/dist/native/base/text.js +53 -0
- package/dist/native/form/checkbox.d.ts +13 -0
- package/dist/native/form/checkbox.js +55 -0
- package/dist/native/form/date-picker.d.ts +23 -0
- package/dist/native/form/date-picker.js +119 -0
- package/dist/native/form/form.d.ts +22 -0
- package/dist/native/form/form.js +44 -0
- package/dist/native/form/radio-group.d.ts +23 -0
- package/dist/native/form/radio-group.js +88 -0
- package/dist/native/form/select.d.ts +13 -0
- package/dist/native/form/select.js +45 -0
- package/dist/native/form/slider.d.ts +14 -0
- package/dist/native/form/slider.js +42 -0
- package/dist/native/form/switch.d.ts +9 -0
- package/dist/native/form/switch.js +59 -0
- package/dist/native/form/text-area.d.ts +11 -0
- package/dist/native/form/text-area.js +50 -0
- package/dist/native/form/text-input.d.ts +18 -0
- package/dist/native/form/text-input.js +90 -0
- package/dist/native/index.d.ts +1 -0
- package/dist/native/index.js +0 -0
- package/dist/native/layout/accordion.d.ts +25 -0
- package/dist/native/layout/accordion.js +54 -0
- package/dist/native/layout/card.d.ts +47 -0
- package/dist/native/layout/card.js +57 -0
- package/dist/native/layout/description.d.ts +16 -0
- package/dist/native/layout/description.js +32 -0
- package/dist/native/layout/error.d.ts +21 -0
- package/dist/native/layout/error.js +44 -0
- package/dist/native/layout/information.d.ts +25 -0
- package/dist/native/layout/information.js +35 -0
- package/dist/native/layout/locked.d.ts +38 -0
- package/dist/native/layout/locked.js +94 -0
- package/dist/native/layout/modal.d.ts +25 -0
- package/dist/native/layout/modal.js +93 -0
- package/dist/native/layout/not-found.d.ts +17 -0
- package/dist/native/layout/not-found.js +30 -0
- package/dist/native/layout/page-frame.d.ts +23 -0
- package/dist/native/layout/page-frame.js +46 -0
- package/dist/native/layout/panel.d.ts +18 -0
- package/dist/native/layout/panel.js +23 -0
- package/dist/native/layout/reorderable-list.d.ts +42 -0
- package/dist/native/layout/reorderable-list.js +52 -0
- package/dist/native/layout/sheet.d.ts +30 -0
- package/dist/native/layout/sheet.js +46 -0
- package/dist/native/layout/simple-dialog.d.ts +16 -0
- package/dist/native/layout/simple-dialog.js +20 -0
- package/dist/native/layout/simple-table.d.ts +50 -0
- package/dist/native/layout/simple-table.js +75 -0
- package/dist/native/layout/tab-bar.d.ts +33 -0
- package/dist/native/layout/tab-bar.js +48 -0
- package/dist/native/layout/tabs.d.ts +28 -0
- package/dist/native/layout/tabs.js +54 -0
- package/dist/native/layout/tuning-panel.d.ts +24 -0
- package/dist/native/layout/tuning-panel.js +246 -0
- package/dist/native/lib/autocomplete.d.ts +7 -0
- package/dist/native/lib/autocomplete.js +34 -0
- package/dist/native/lib/breakpoints.d.ts +14 -0
- package/dist/native/lib/breakpoints.js +17 -0
- package/dist/native/lib/chart-palette.d.ts +8 -0
- package/dist/native/lib/chart-palette.js +20 -0
- package/dist/native/lib/confirm.d.ts +48 -0
- package/dist/native/lib/confirm.js +69 -0
- package/dist/native/lib/control.d.ts +24 -0
- package/dist/native/lib/control.js +0 -0
- package/dist/native/lib/external-store.d.ts +16 -0
- package/dist/native/lib/external-store.js +30 -0
- package/dist/native/lib/keyboard.d.ts +15 -0
- package/dist/native/lib/keyboard.js +24 -0
- package/dist/native/lib/labels.d.ts +15 -0
- package/dist/native/lib/labels.js +17 -0
- package/dist/native/lib/loading.d.ts +10 -0
- package/dist/native/lib/loading.js +15 -0
- package/dist/native/lib/network.d.ts +11 -0
- package/dist/native/lib/network.js +20 -0
- package/dist/native/lib/scheme.d.ts +18 -0
- package/dist/native/lib/scheme.js +22 -0
- package/dist/native/lib/snackbar.d.ts +45 -0
- package/dist/native/lib/snackbar.js +59 -0
- package/dist/native/lib/theme.d.ts +34 -0
- package/dist/native/lib/theme.js +53 -0
- package/dist/native/lib/timezone.d.ts +26 -0
- package/dist/native/lib/timezone.js +95 -0
- package/dist/native/lib/token-color.d.ts +5 -0
- package/dist/native/lib/token-color.js +13 -0
- package/dist/native/lib/token-color.web.d.ts +4 -0
- package/dist/native/lib/token-color.web.js +7 -0
- package/dist/native/lib/tuning-context.d.ts +9 -0
- package/dist/native/lib/tuning-context.js +7 -0
- package/dist/native/lib/tuning.d.ts +24 -0
- package/dist/native/lib/tuning.js +42 -0
- package/dist/native/lib/typography.d.ts +10 -0
- package/dist/native/lib/typography.js +11 -0
- package/dist/native/lib/utils.d.ts +11 -0
- package/dist/native/lib/utils.js +21 -0
- package/dist/native/once/confirm.d.ts +7 -0
- package/dist/native/once/confirm.js +60 -0
- package/dist/native/once/error-boundary.d.ts +28 -0
- package/dist/native/once/error-boundary.js +55 -0
- package/dist/native/once/loading-lock.d.ts +8 -0
- package/dist/native/once/loading-lock.js +28 -0
- package/dist/native/once/offline-banner.d.ts +15 -0
- package/dist/native/once/offline-banner.js +35 -0
- package/dist/native/once/snackbar.d.ts +17 -0
- package/dist/native/once/snackbar.js +106 -0
- package/dist/native/styles.css +46 -0
- package/dist/shared/analytics.d.ts +71 -0
- package/dist/shared/analytics.js +0 -0
- package/dist/shared/button.d.ts +7 -0
- package/dist/shared/button.js +23 -0
- package/dist/shared/form.d.ts +45 -0
- package/dist/shared/form.js +46 -0
- package/dist/shared/index.d.ts +3 -0
- package/dist/shared/index.js +3 -0
- package/dist/tokens/contrast-pairs.d.ts +30 -0
- package/dist/tokens/contrast-pairs.js +404 -0
- package/dist/tokens/index.d.ts +6 -0
- package/dist/tokens/index.js +10 -0
- package/dist/tokens/styles.gen.css +250 -0
- package/dist/tokens/tokens.gen.d.ts +141 -0
- package/dist/tokens/tokens.gen.js +206 -0
- package/dist/tuning/catalog.d.ts +27 -0
- package/dist/tuning/catalog.gen.d.ts +4 -0
- package/dist/tuning/catalog.gen.js +397 -0
- package/dist/tuning/catalog.js +128 -0
- package/dist/tuning/color.d.ts +20 -0
- package/dist/tuning/color.js +80 -0
- package/dist/tuning/css.d.ts +35 -0
- package/dist/tuning/css.js +147 -0
- package/dist/tuning/index.d.ts +8 -0
- package/dist/tuning/index.js +9 -0
- package/dist/tuning/model.d.ts +33 -0
- package/dist/tuning/model.js +154 -0
- package/dist/tuning/native.d.ts +35 -0
- package/dist/tuning/native.js +80 -0
- package/dist/tuning/schema.d.ts +69 -0
- package/dist/tuning/schema.js +247 -0
- package/dist/tuning/types.d.ts +75 -0
- package/dist/tuning/types.js +39 -0
- package/dist/web/analytics/line-chart.d.ts +20 -0
- package/dist/web/analytics/line-chart.js +28 -0
- package/dist/web/analytics/metric-card.d.ts +18 -0
- package/dist/web/analytics/metric-card.js +40 -0
- package/dist/web/analytics/multi-line-chart.d.ts +39 -0
- package/dist/web/analytics/multi-line-chart.js +345 -0
- package/dist/web/atom/avatar.d.ts +11 -0
- package/dist/web/atom/avatar.js +24 -0
- package/dist/web/atom/badge.d.ts +2 -0
- package/dist/web/atom/badge.js +3 -0
- package/dist/web/atom/button.d.ts +23 -0
- package/dist/web/atom/button.js +35 -0
- package/dist/web/atom/checkbox.d.ts +19 -0
- package/dist/web/atom/checkbox.js +33 -0
- package/dist/web/atom/colored-value.d.ts +13 -0
- package/dist/web/atom/colored-value.js +24 -0
- package/dist/web/atom/help.d.ts +10 -0
- package/dist/web/atom/help.js +18 -0
- package/dist/web/atom/label.d.ts +2 -0
- package/dist/web/atom/label.js +3 -0
- package/dist/web/atom/segmented-control.d.ts +39 -0
- package/dist/web/atom/segmented-control.js +42 -0
- package/dist/web/atom/select.d.ts +43 -0
- package/dist/web/atom/select.js +93 -0
- package/dist/web/atom/separator.d.ts +2 -0
- package/dist/web/atom/separator.js +3 -0
- package/dist/web/atom/skeleton.d.ts +2 -0
- package/dist/web/atom/skeleton.js +3 -0
- package/dist/web/atom/slider.d.ts +33 -0
- package/dist/web/atom/slider.js +70 -0
- package/dist/web/atom/spinner.d.ts +8 -0
- package/dist/web/atom/spinner.js +14 -0
- package/dist/web/atom/switch.d.ts +11 -0
- package/dist/web/atom/switch.js +10 -0
- package/dist/web/atom/text-area.d.ts +23 -0
- package/dist/web/atom/text-area.js +27 -0
- package/dist/web/atom/text-field.d.ts +18 -0
- package/dist/web/atom/text-field.js +22 -0
- package/dist/web/atom/toggle-chip.d.ts +22 -0
- package/dist/web/atom/toggle-chip.js +28 -0
- package/dist/web/atom/tooltip.d.ts +23 -0
- package/dist/web/atom/tooltip.js +26 -0
- package/dist/web/atom/typography.d.ts +6 -0
- package/dist/web/atom/typography.js +23 -0
- package/dist/web/base/accordion.d.ts +9 -0
- package/dist/web/base/accordion.js +44 -0
- package/dist/web/base/alert.d.ts +11 -0
- package/dist/web/base/alert.js +37 -0
- package/dist/web/base/avatar.d.ts +8 -0
- package/dist/web/base/avatar.js +29 -0
- package/dist/web/base/badge.d.ts +12 -0
- package/dist/web/base/badge.js +26 -0
- package/dist/web/base/breadcrumb.d.ts +16 -0
- package/dist/web/base/breadcrumb.js +72 -0
- package/dist/web/base/button.d.ts +12 -0
- package/dist/web/base/button.js +47 -0
- package/dist/web/base/card.d.ts +19 -0
- package/dist/web/base/card.js +74 -0
- package/dist/web/base/checkbox.d.ts +6 -0
- package/dist/web/base/checkbox.js +21 -0
- package/dist/web/base/dialog.d.ts +20 -0
- package/dist/web/base/dialog.js +92 -0
- package/dist/web/base/dropdown-menu.d.ts +29 -0
- package/dist/web/base/dropdown-menu.js +125 -0
- package/dist/web/base/field.d.ts +27 -0
- package/dist/web/base/field.js +118 -0
- package/dist/web/base/form.d.ts +38 -0
- package/dist/web/base/form.js +110 -0
- package/dist/web/base/input.d.ts +9 -0
- package/dist/web/base/input.js +23 -0
- package/dist/web/base/label.d.ts +6 -0
- package/dist/web/base/label.js +15 -0
- package/dist/web/base/pagination.d.ts +34 -0
- package/dist/web/base/pagination.js +90 -0
- package/dist/web/base/popover.d.ts +11 -0
- package/dist/web/base/popover.js +37 -0
- package/dist/web/base/radio-group.d.ts +7 -0
- package/dist/web/base/radio-group.js +27 -0
- package/dist/web/base/scroll-area.d.ts +10 -0
- package/dist/web/base/scroll-area.js +41 -0
- package/dist/web/base/select.d.ts +17 -0
- package/dist/web/base/select.js +96 -0
- package/dist/web/base/separator.d.ts +6 -0
- package/dist/web/base/separator.js +17 -0
- package/dist/web/base/sheet.d.ts +19 -0
- package/dist/web/base/sheet.js +88 -0
- package/dist/web/base/skeleton.d.ts +5 -0
- package/dist/web/base/skeleton.js +14 -0
- package/dist/web/base/slider.d.ts +9 -0
- package/dist/web/base/slider.js +39 -0
- package/dist/web/base/sonner.d.ts +9 -0
- package/dist/web/base/sonner.js +25 -0
- package/dist/web/base/spinner.d.ts +5 -0
- package/dist/web/base/spinner.js +17 -0
- package/dist/web/base/switch.d.ts +6 -0
- package/dist/web/base/switch.js +19 -0
- package/dist/web/base/table.d.ts +14 -0
- package/dist/web/base/table.js +68 -0
- package/dist/web/base/tabs.d.ts +9 -0
- package/dist/web/base/tabs.js +36 -0
- package/dist/web/base/textarea.d.ts +9 -0
- package/dist/web/base/textarea.js +23 -0
- package/dist/web/base/tooltip.d.ts +9 -0
- package/dist/web/base/tooltip.js +36 -0
- package/dist/web/form/checkbox.d.ts +35 -0
- package/dist/web/form/checkbox.js +91 -0
- package/dist/web/form/radio-group.d.ts +24 -0
- package/dist/web/form/radio-group.js +75 -0
- package/dist/web/form/select.d.ts +16 -0
- package/dist/web/form/select.js +44 -0
- package/dist/web/form/slider.d.ts +19 -0
- package/dist/web/form/slider.js +51 -0
- package/dist/web/form/switch.d.ts +11 -0
- package/dist/web/form/switch.js +50 -0
- package/dist/web/form/text-area.d.ts +10 -0
- package/dist/web/form/text-area.js +31 -0
- package/dist/web/form/text-input.d.ts +10 -0
- package/dist/web/form/text-input.js +42 -0
- package/dist/web/index.d.ts +1 -0
- package/dist/web/index.js +0 -0
- package/dist/web/layout/accordion.d.ts +26 -0
- package/dist/web/layout/accordion.js +29 -0
- package/dist/web/layout/alert-modal.d.ts +41 -0
- package/dist/web/layout/alert-modal.js +71 -0
- package/dist/web/layout/card.d.ts +17 -0
- package/dist/web/layout/card.js +35 -0
- package/dist/web/layout/description.d.ts +12 -0
- package/dist/web/layout/description.js +20 -0
- package/dist/web/layout/information.d.ts +36 -0
- package/dist/web/layout/information.js +53 -0
- package/dist/web/layout/modal.d.ts +16 -0
- package/dist/web/layout/modal.js +37 -0
- package/dist/web/layout/page-frame.d.ts +37 -0
- package/dist/web/layout/page-frame.js +79 -0
- package/dist/web/layout/scroll-area.d.ts +10 -0
- package/dist/web/layout/scroll-area.js +13 -0
- package/dist/web/layout/sheet.d.ts +32 -0
- package/dist/web/layout/sheet.js +68 -0
- package/dist/web/layout/simple-dialog.d.ts +11 -0
- package/dist/web/layout/simple-dialog.js +24 -0
- package/dist/web/layout/simple-table.d.ts +49 -0
- package/dist/web/layout/simple-table.js +58 -0
- package/dist/web/layout/tabs.d.ts +26 -0
- package/dist/web/layout/tabs.js +42 -0
- package/dist/web/layout/titled-modal.d.ts +32 -0
- package/dist/web/layout/titled-modal.js +58 -0
- package/dist/web/lib/css-vars.d.ts +14 -0
- package/dist/web/lib/css-vars.js +18 -0
- package/dist/web/lib/dialog.d.ts +13 -0
- package/dist/web/lib/dialog.js +0 -0
- package/dist/web/lib/form.d.ts +2 -0
- package/dist/web/lib/form.js +3 -0
- package/dist/web/lib/labels.d.ts +27 -0
- package/dist/web/lib/labels.js +29 -0
- package/dist/web/lib/modal-open-focus.d.ts +17 -0
- package/dist/web/lib/modal-open-focus.js +44 -0
- package/dist/web/lib/restore-focus.d.ts +12 -0
- package/dist/web/lib/restore-focus.js +32 -0
- package/dist/web/lib/utils.d.ts +4 -0
- package/dist/web/lib/utils.js +10 -0
- package/dist/web/styles.css +162 -0
- package/package.json +203 -4
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ComponentProps, ReactNode } from "react";
|
|
2
|
+
import { Link as Link$1 } from "expo-router";
|
|
3
|
+
//#region src/native/atom/link.d.ts
|
|
4
|
+
export type LinkProps = ComponentProps<typeof Link$1> & {
|
|
5
|
+
disabled?: boolean;
|
|
6
|
+
children: ReactNode;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* A styled expo-router `Link`. Mirrors the web atom/link
|
|
10
|
+
* (which wraps TanStack Router's `Link`). The `href` type stays the router's own.
|
|
11
|
+
*
|
|
12
|
+
* The text color is `text-foreground` (without a color of its own, the link would stay black on a dark background unless the parent passed one). It can be overridden via className.
|
|
13
|
+
*
|
|
14
|
+
* It can only render inside an expo-router navigation tree, so it has no story on a device
|
|
15
|
+
* (the same reason `base/` is excluded from Storybook). Previews and vitest render it by substituting `<a href>` (`web/expo-router.tsx`).
|
|
16
|
+
*/
|
|
17
|
+
export declare function Link({ disabled, className, children, ...props }: LinkProps): import("react").JSX.Element;
|
|
18
|
+
//#endregion
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { cn } from "../lib/utils.js";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { Link as Link$1 } from "expo-router";
|
|
4
|
+
|
|
5
|
+
//#region src/native/atom/link.tsx
|
|
6
|
+
/**
|
|
7
|
+
* A styled expo-router `Link`. Mirrors the web atom/link
|
|
8
|
+
* (which wraps TanStack Router's `Link`). The `href` type stays the router's own.
|
|
9
|
+
*
|
|
10
|
+
* The text color is `text-foreground` (without a color of its own, the link would stay black on a dark background unless the parent passed one). It can be overridden via className.
|
|
11
|
+
*
|
|
12
|
+
* It can only render inside an expo-router navigation tree, so it has no story on a device
|
|
13
|
+
* (the same reason `base/` is excluded from Storybook). Previews and vitest render it by substituting `<a href>` (`web/expo-router.tsx`).
|
|
14
|
+
*/
|
|
15
|
+
function Link({ disabled, className, children, ...props }) {
|
|
16
|
+
return /* @__PURE__ */ jsx(Link$1, {
|
|
17
|
+
...props,
|
|
18
|
+
disabled,
|
|
19
|
+
className: cn("text-foreground text-sm font-bold underline", disabled && "opacity-50", className),
|
|
20
|
+
children
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
//#endregion
|
|
25
|
+
export { Link };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
//#region src/native/atom/readout.d.ts
|
|
2
|
+
export type ReadoutProps = {
|
|
3
|
+
/** Metric name in all caps (e.g. NET PROFIT). */
|
|
4
|
+
label: string;
|
|
5
|
+
value: string;
|
|
6
|
+
/**
|
|
7
|
+
* The value color. Reserved for callers passing a **theme-independent color with a fixed meaning**,
|
|
8
|
+
* such as gain/loss. Defaults to `text-foreground`.
|
|
9
|
+
*/
|
|
10
|
+
valueColor?: string;
|
|
11
|
+
sub?: string;
|
|
12
|
+
/** Large (for detail headers) or regular. */
|
|
13
|
+
size?: "md" | "lg";
|
|
14
|
+
className?: string;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* An instrument-style readout, matching the inside of the web MetricCard:
|
|
18
|
+
* three tiers of an all-caps muted label, a large bold number and secondary text.
|
|
19
|
+
* The number is monospaced (Geist Mono + tabular) so the digits line up.
|
|
20
|
+
*/
|
|
21
|
+
export declare function Readout({ label, value, valueColor, sub, size, className }: ReadoutProps): import("react").JSX.Element;
|
|
22
|
+
//#endregion
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { cn } from "../lib/utils.js";
|
|
2
|
+
import { Text as Text$1 } from "../base/text.js";
|
|
3
|
+
import { tabularNums } from "../lib/typography.js";
|
|
4
|
+
import { View } from "react-native";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
|
|
7
|
+
//#region src/native/atom/readout.tsx
|
|
8
|
+
/**
|
|
9
|
+
* An instrument-style readout, matching the inside of the web MetricCard:
|
|
10
|
+
* three tiers of an all-caps muted label, a large bold number and secondary text.
|
|
11
|
+
* The number is monospaced (Geist Mono + tabular) so the digits line up.
|
|
12
|
+
*/
|
|
13
|
+
function Readout({ label, value, valueColor, sub, size = "md", className }) {
|
|
14
|
+
return /* @__PURE__ */ jsxs(View, {
|
|
15
|
+
className: cn("gap-1", className),
|
|
16
|
+
children: [
|
|
17
|
+
/* @__PURE__ */ jsx(Text$1, {
|
|
18
|
+
className: "text-sm font-medium uppercase text-muted-foreground",
|
|
19
|
+
children: label
|
|
20
|
+
}),
|
|
21
|
+
/* @__PURE__ */ jsx(Text$1, {
|
|
22
|
+
style: [tabularNums, valueColor ? { color: valueColor } : null],
|
|
23
|
+
numberOfLines: 1,
|
|
24
|
+
adjustsFontSizeToFit: true,
|
|
25
|
+
minimumFontScale: .6,
|
|
26
|
+
className: cn("font-mono font-bold text-foreground", size === "lg" ? "text-4xl" : "text-2xl"),
|
|
27
|
+
children: value
|
|
28
|
+
}),
|
|
29
|
+
sub ? /* @__PURE__ */ jsx(Text$1, {
|
|
30
|
+
style: tabularNums,
|
|
31
|
+
className: "font-mono text-xs text-muted-foreground",
|
|
32
|
+
children: sub
|
|
33
|
+
}) : null
|
|
34
|
+
]
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
//#endregion
|
|
39
|
+
export { Readout };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
//#region src/native/atom/search-input.d.ts
|
|
2
|
+
export type SearchInputProps = {
|
|
3
|
+
value: string;
|
|
4
|
+
onChangeText: (text: string) => void;
|
|
5
|
+
placeholder: string;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* A search input. Matches the web SearchInput with the same structure: control corner radius, a soft surface,
|
|
9
|
+
* and a leading search icon (no Liquid Glass capsule).
|
|
10
|
+
*/
|
|
11
|
+
export declare function SearchInput({ value, onChangeText, placeholder }: SearchInputProps): import("react").JSX.Element;
|
|
12
|
+
//#endregion
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { useTokenColor } from "../lib/token-color.js";
|
|
2
|
+
import { Symbol } from "./symbol.js";
|
|
3
|
+
import { TextInput, View } from "react-native";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
|
|
6
|
+
//#region src/native/atom/search-input.tsx
|
|
7
|
+
/**
|
|
8
|
+
* A search input. Matches the web SearchInput with the same structure: control corner radius, a soft surface,
|
|
9
|
+
* and a leading search icon (no Liquid Glass capsule).
|
|
10
|
+
*/
|
|
11
|
+
function SearchInput({ value, onChangeText, placeholder }) {
|
|
12
|
+
const mutedInk = useTokenColor("--ink-500");
|
|
13
|
+
return /* @__PURE__ */ jsxs(View, {
|
|
14
|
+
className: "relative flex-row items-center",
|
|
15
|
+
children: [/* @__PURE__ */ jsx(View, {
|
|
16
|
+
className: "absolute left-3.5 z-10",
|
|
17
|
+
children: /* @__PURE__ */ jsx(Symbol, {
|
|
18
|
+
name: "magnifyingglass",
|
|
19
|
+
size: 16,
|
|
20
|
+
tintColor: mutedInk
|
|
21
|
+
})
|
|
22
|
+
}), /* @__PURE__ */ jsx(TextInput, {
|
|
23
|
+
placeholder,
|
|
24
|
+
placeholderTextColor: mutedInk,
|
|
25
|
+
value,
|
|
26
|
+
onChangeText,
|
|
27
|
+
autoCapitalize: "none",
|
|
28
|
+
autoCorrect: false,
|
|
29
|
+
clearButtonMode: "while-editing",
|
|
30
|
+
className: "min-h-9 w-full rounded-control bg-muted/50 py-1.5 pl-10 pr-10 text-sm text-foreground"
|
|
31
|
+
})]
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
//#endregion
|
|
36
|
+
export { SearchInput };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { ControlA11yProps } from "../lib/control.js";
|
|
2
|
+
import { ReactNode } from "react";
|
|
3
|
+
//#region src/native/atom/select.d.ts
|
|
4
|
+
export type SelectOption = {
|
|
5
|
+
value: string;
|
|
6
|
+
label: string;
|
|
7
|
+
};
|
|
8
|
+
export type SelectOptionGroup = {
|
|
9
|
+
label: string;
|
|
10
|
+
options: SelectOption[];
|
|
11
|
+
};
|
|
12
|
+
export type SelectProps = ControlA11yProps & {
|
|
13
|
+
value: string;
|
|
14
|
+
onValueChange: (value: string) => void;
|
|
15
|
+
options: (SelectOption | SelectOptionGroup)[];
|
|
16
|
+
placeholder?: string;
|
|
17
|
+
label?: ReactNode;
|
|
18
|
+
required?: boolean;
|
|
19
|
+
description?: ReactNode;
|
|
20
|
+
helpText?: ReactNode;
|
|
21
|
+
disabled?: boolean;
|
|
22
|
+
/** Error state. The trigger's border becomes destructive and `aria-invalid` is set (inside a form, the `aria-invalid` passed by `FormControl` has the same effect). */
|
|
23
|
+
invalid?: boolean;
|
|
24
|
+
size?: "xs" | "sm" | "default";
|
|
25
|
+
/** Controls open/closed (internal state when omitted). */
|
|
26
|
+
open?: boolean;
|
|
27
|
+
onOpenChange?: (open: boolean) => void;
|
|
28
|
+
/** The picker heading (falls back to `label`, then `placeholder`). It becomes the dialog's name. */
|
|
29
|
+
sheetTitle?: ReactNode;
|
|
30
|
+
/** Screen reader name of the picker's close button (the default is the Japanese "close" label). */
|
|
31
|
+
closeLabel?: string;
|
|
32
|
+
/**
|
|
33
|
+
* The trigger's name (when there is no visible label; a string `label` is the default). It is read as "name, current value"
|
|
34
|
+
* (the trigger is a button that opens a sheet, so the value is included in the name).
|
|
35
|
+
*/
|
|
36
|
+
accessibilityLabel?: string;
|
|
37
|
+
/** Slot for the form to insert an error. */
|
|
38
|
+
errorSlot?: ReactNode;
|
|
39
|
+
className?: string;
|
|
40
|
+
wrapperClassName?: string;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* A controlled-only Select. It has the same API as the web atom/select (flat / grouped options,
|
|
44
|
+
* label, description, error slot, `open` / `onOpenChange`). There is no search, just like on the web.
|
|
45
|
+
*
|
|
46
|
+
* The web uses a Radix popover, but native lets the user choose in a bottom sheet (`Modal`).
|
|
47
|
+
* The trigger looks the same as the web input frame (control corner radius, 1px line-strong border, raised surface).
|
|
48
|
+
*
|
|
49
|
+
* Accessibility: the trigger is a `button` (`aria-expanded`), not the web's `combobox` (pressing it opens a **dialog**).
|
|
50
|
+
* Its name is "label, current value". The sheet is a dialog whose name is the heading (`sheetTitle`). The options are `radio`s in a `radiogroup`
|
|
51
|
+
* (`aria-checked`; each group is a radiogroup named by its heading).
|
|
52
|
+
*/
|
|
53
|
+
export declare function Select({ value, onValueChange, options, placeholder, label, required, description, helpText, disabled, invalid, size, open, onOpenChange, sheetTitle, closeLabel, accessibilityLabel, errorSlot, className, wrapperClassName, id, accessibilityHint, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, "aria-invalid": ariaInvalid }: SelectProps): import("react").JSX.Element;
|
|
54
|
+
//#endregion
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import { useTokenColor } from "../lib/token-color.js";
|
|
2
|
+
import { cn, isBlankNode } from "../lib/utils.js";
|
|
3
|
+
import { Text as Text$1 } from "../base/text.js";
|
|
4
|
+
import { activateOnSpace } from "../lib/keyboard.js";
|
|
5
|
+
import { Label } from "./label.js";
|
|
6
|
+
import { SELECT_LABEL } from "../lib/labels.js";
|
|
7
|
+
import { SheetHeader, SheetScroll, SheetShell } from "../base/sheet.js";
|
|
8
|
+
import { useId, useState } from "react";
|
|
9
|
+
import { Pressable, View } from "react-native";
|
|
10
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
11
|
+
import Feather from "@expo/vector-icons/Feather";
|
|
12
|
+
|
|
13
|
+
//#region src/native/atom/select.tsx
|
|
14
|
+
const triggerHeight = {
|
|
15
|
+
xs: "h-7",
|
|
16
|
+
sm: "h-8",
|
|
17
|
+
default: "h-9"
|
|
18
|
+
};
|
|
19
|
+
function isOptionGroup(option) {
|
|
20
|
+
return "options" in option;
|
|
21
|
+
}
|
|
22
|
+
function flatten(options) {
|
|
23
|
+
return options.flatMap((option) => isOptionGroup(option) ? option.options : [option]);
|
|
24
|
+
}
|
|
25
|
+
/** Groups consecutive non-group options into one segment (so that each becomes a single radiogroup). */
|
|
26
|
+
function toSegments(options) {
|
|
27
|
+
const segments = [];
|
|
28
|
+
for (const option of options) {
|
|
29
|
+
if (isOptionGroup(option)) {
|
|
30
|
+
segments.push({
|
|
31
|
+
kind: "labelled",
|
|
32
|
+
section: option
|
|
33
|
+
});
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
const last = segments.at(-1);
|
|
37
|
+
if (last?.kind === "plain") last.options.push(option);
|
|
38
|
+
else segments.push({
|
|
39
|
+
kind: "plain",
|
|
40
|
+
options: [option]
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
return segments;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* A controlled-only Select. It has the same API as the web atom/select (flat / grouped options,
|
|
47
|
+
* label, description, error slot, `open` / `onOpenChange`). There is no search, just like on the web.
|
|
48
|
+
*
|
|
49
|
+
* The web uses a Radix popover, but native lets the user choose in a bottom sheet (`Modal`).
|
|
50
|
+
* The trigger looks the same as the web input frame (control corner radius, 1px line-strong border, raised surface).
|
|
51
|
+
*
|
|
52
|
+
* Accessibility: the trigger is a `button` (`aria-expanded`), not the web's `combobox` (pressing it opens a **dialog**).
|
|
53
|
+
* Its name is "label, current value". The sheet is a dialog whose name is the heading (`sheetTitle`). The options are `radio`s in a `radiogroup`
|
|
54
|
+
* (`aria-checked`; each group is a radiogroup named by its heading).
|
|
55
|
+
*/
|
|
56
|
+
function Select({ value, onValueChange, options, placeholder, label, required, description, helpText, disabled, invalid, size = "default", open, onOpenChange, sheetTitle, closeLabel, accessibilityLabel, errorSlot, className, wrapperClassName, id, accessibilityHint, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, "aria-invalid": ariaInvalid }) {
|
|
57
|
+
const [internalOpen, setInternalOpen] = useState(false);
|
|
58
|
+
const isOpen = open ?? internalOpen;
|
|
59
|
+
const setOpen = (next) => {
|
|
60
|
+
onOpenChange?.(next);
|
|
61
|
+
if (open === void 0) setInternalOpen(next);
|
|
62
|
+
};
|
|
63
|
+
const generatedId = useId();
|
|
64
|
+
const triggerId = id ?? `${generatedId}-trigger`;
|
|
65
|
+
const labelId = `${generatedId}-label`;
|
|
66
|
+
const valueId = `${generatedId}-value`;
|
|
67
|
+
const descriptionId = `${generatedId}-description`;
|
|
68
|
+
const sheetTitleId = `${generatedId}-sheet-title`;
|
|
69
|
+
const mutedInk = useTokenColor("--ink-500");
|
|
70
|
+
const ink = useTokenColor("--ink-1000");
|
|
71
|
+
const selected = flatten(options).find((option) => option.value === value);
|
|
72
|
+
const valueText = selected?.label ?? placeholder ?? "";
|
|
73
|
+
const hasLabel = !isBlankNode(label);
|
|
74
|
+
const hasDescription = !isBlankNode(description);
|
|
75
|
+
const resolvedSheetTitle = [
|
|
76
|
+
sheetTitle,
|
|
77
|
+
label,
|
|
78
|
+
placeholder,
|
|
79
|
+
accessibilityLabel
|
|
80
|
+
].find((candidate) => !isBlankNode(candidate)) ?? "選択肢";
|
|
81
|
+
const labelledBy = ariaLabelledBy ?? (hasLabel ? labelId : void 0);
|
|
82
|
+
const nameText = accessibilityLabel ?? (typeof label === "string" ? label : void 0);
|
|
83
|
+
const describedBy = ariaDescribedBy ?? (hasDescription ? descriptionId : void 0);
|
|
84
|
+
const isInvalid = invalid ?? ariaInvalid;
|
|
85
|
+
const trigger = /* @__PURE__ */ jsxs(Pressable, {
|
|
86
|
+
id: triggerId,
|
|
87
|
+
accessibilityRole: "button",
|
|
88
|
+
accessibilityLabel: nameText === void 0 ? void 0 : `${nameText}、${valueText}`,
|
|
89
|
+
accessibilityHint,
|
|
90
|
+
"aria-labelledby": labelledBy === void 0 ? void 0 : `${labelledBy} ${valueId}`,
|
|
91
|
+
"aria-describedby": describedBy,
|
|
92
|
+
"aria-invalid": isInvalid ? true : void 0,
|
|
93
|
+
"aria-expanded": isOpen,
|
|
94
|
+
"aria-disabled": disabled,
|
|
95
|
+
onPress: () => setOpen(true),
|
|
96
|
+
disabled,
|
|
97
|
+
className: cn("w-full flex-row items-center justify-between gap-2 rounded-control border bg-raised px-3", triggerHeight[size], isInvalid ? "border-destructive" : "border-line-strong", disabled && "opacity-50", className),
|
|
98
|
+
children: [/* @__PURE__ */ jsx(Text$1, {
|
|
99
|
+
id: valueId,
|
|
100
|
+
className: cn("text-sm", selected ? "text-foreground" : "text-muted-foreground"),
|
|
101
|
+
numberOfLines: 1,
|
|
102
|
+
children: valueText
|
|
103
|
+
}), /* @__PURE__ */ jsx(Feather, {
|
|
104
|
+
name: "chevron-down",
|
|
105
|
+
size: 14,
|
|
106
|
+
color: mutedInk
|
|
107
|
+
})]
|
|
108
|
+
});
|
|
109
|
+
const choose = (next) => {
|
|
110
|
+
onValueChange(next);
|
|
111
|
+
setOpen(false);
|
|
112
|
+
};
|
|
113
|
+
const sheet = /* @__PURE__ */ jsxs(SheetShell, {
|
|
114
|
+
open: isOpen,
|
|
115
|
+
onOpenChange: setOpen,
|
|
116
|
+
maxHeightRatio: .7,
|
|
117
|
+
"aria-labelledby": sheetTitleId,
|
|
118
|
+
children: [/* @__PURE__ */ jsx(SheetHeader, {
|
|
119
|
+
title: resolvedSheetTitle,
|
|
120
|
+
closeLabel,
|
|
121
|
+
onClose: () => setOpen(false),
|
|
122
|
+
titleId: sheetTitleId
|
|
123
|
+
}), /* @__PURE__ */ jsx(SheetScroll, {
|
|
124
|
+
padded: false,
|
|
125
|
+
children: toSegments(options).map((segment, index) => segment.kind === "labelled" ? /* @__PURE__ */ jsx(GroupedRows, {
|
|
126
|
+
section: segment.section,
|
|
127
|
+
value,
|
|
128
|
+
tint: ink,
|
|
129
|
+
onChoose: choose
|
|
130
|
+
}, `labelled-${index.toString()}-${segment.section.label}`) : /* @__PURE__ */ jsx(View, {
|
|
131
|
+
role: "radiogroup",
|
|
132
|
+
"aria-labelledby": sheetTitleId,
|
|
133
|
+
children: segment.options.map((option) => /* @__PURE__ */ jsx(Row, {
|
|
134
|
+
option,
|
|
135
|
+
selected: option.value === value,
|
|
136
|
+
tint: ink,
|
|
137
|
+
onPress: () => choose(option.value)
|
|
138
|
+
}, option.value))
|
|
139
|
+
}, `plain-${index.toString()}`))
|
|
140
|
+
})]
|
|
141
|
+
});
|
|
142
|
+
if (!hasLabel && !hasDescription && !errorSlot) return /* @__PURE__ */ jsxs(Fragment$1, { children: [trigger, sheet] });
|
|
143
|
+
return /* @__PURE__ */ jsxs(View, {
|
|
144
|
+
className: cn("gap-1.5", wrapperClassName),
|
|
145
|
+
children: [
|
|
146
|
+
hasLabel ? /* @__PURE__ */ jsx(Label, {
|
|
147
|
+
id: labelId,
|
|
148
|
+
required,
|
|
149
|
+
helpText,
|
|
150
|
+
className: "text-xs font-semibold opacity-80",
|
|
151
|
+
children: label
|
|
152
|
+
}) : null,
|
|
153
|
+
trigger,
|
|
154
|
+
hasDescription ? /* @__PURE__ */ jsx(Text$1, {
|
|
155
|
+
id: descriptionId,
|
|
156
|
+
className: "text-muted-foreground text-xs",
|
|
157
|
+
children: description
|
|
158
|
+
}) : null,
|
|
159
|
+
errorSlot,
|
|
160
|
+
sheet
|
|
161
|
+
]
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
function GroupedRows({ section, value, tint, onChoose }) {
|
|
165
|
+
const headingId = useId();
|
|
166
|
+
return /* @__PURE__ */ jsxs(View, {
|
|
167
|
+
role: "radiogroup",
|
|
168
|
+
"aria-labelledby": headingId,
|
|
169
|
+
children: [/* @__PURE__ */ jsx(Text$1, {
|
|
170
|
+
id: headingId,
|
|
171
|
+
className: "text-muted-foreground border-b border-line px-4 py-2 text-xs font-semibold uppercase",
|
|
172
|
+
children: section.label
|
|
173
|
+
}), section.options.map((option) => /* @__PURE__ */ jsx(Row, {
|
|
174
|
+
option,
|
|
175
|
+
selected: option.value === value,
|
|
176
|
+
tint,
|
|
177
|
+
onPress: () => onChoose(option.value)
|
|
178
|
+
}, option.value))]
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
function Row({ option, selected, tint, onPress }) {
|
|
182
|
+
return /* @__PURE__ */ jsxs(Pressable, {
|
|
183
|
+
accessibilityRole: "radio",
|
|
184
|
+
"aria-checked": selected,
|
|
185
|
+
onPress,
|
|
186
|
+
onKeyDown: activateOnSpace(onPress),
|
|
187
|
+
className: cn("flex-row items-center justify-between border-b border-line px-4 py-3", selected && "bg-wash"),
|
|
188
|
+
children: [/* @__PURE__ */ jsx(Text$1, {
|
|
189
|
+
className: "text-foreground text-base",
|
|
190
|
+
children: option.label
|
|
191
|
+
}), selected ? /* @__PURE__ */ jsx(Feather, {
|
|
192
|
+
name: "check",
|
|
193
|
+
size: 16,
|
|
194
|
+
color: tint
|
|
195
|
+
}) : null]
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
//#endregion
|
|
200
|
+
export { Select };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
//#region src/native/atom/separator.d.ts
|
|
2
|
+
export type SeparatorProps = {
|
|
3
|
+
orientation?: "horizontal" | "vertical";
|
|
4
|
+
className?: string;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* A 1px divider line. Same role as the web base/separator.
|
|
8
|
+
*
|
|
9
|
+
* Use `bg-line` rather than `bg-border` for the color (`--border` can fail to follow dark mode after its value is folded).
|
|
10
|
+
*/
|
|
11
|
+
export declare function Separator({ orientation, className }: SeparatorProps): import("react").JSX.Element;
|
|
12
|
+
//#endregion
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { cn } from "../lib/utils.js";
|
|
2
|
+
import { View } from "react-native";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
|
|
5
|
+
//#region src/native/atom/separator.tsx
|
|
6
|
+
/**
|
|
7
|
+
* A 1px divider line. Same role as the web base/separator.
|
|
8
|
+
*
|
|
9
|
+
* Use `bg-line` rather than `bg-border` for the color (`--border` can fail to follow dark mode after its value is folded).
|
|
10
|
+
*/
|
|
11
|
+
function Separator({ orientation = "horizontal", className }) {
|
|
12
|
+
return /* @__PURE__ */ jsx(View, { className: cn("bg-line shrink-0", orientation === "horizontal" ? "h-px w-full" : "h-full w-px", className) });
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
//#endregion
|
|
16
|
+
export { Separator };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
//#region src/native/atom/skeleton.d.ts
|
|
2
|
+
export type SkeletonProps = {
|
|
3
|
+
className?: string;
|
|
4
|
+
};
|
|
5
|
+
/**
|
|
6
|
+
* A loading placeholder. The same pale surface + pulse as the web base/skeleton.
|
|
7
|
+
*
|
|
8
|
+
* The web uses `animate-pulse` (a CSS animation), but native should not depend on
|
|
9
|
+
* CSS animation support, so `Animated` produces the same 2-second pulse.
|
|
10
|
+
*/
|
|
11
|
+
export declare function Skeleton({ className }: SkeletonProps): import("react").JSX.Element;
|
|
12
|
+
//#endregion
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { cn } from "../lib/utils.js";
|
|
2
|
+
import { useEffect, useRef } from "react";
|
|
3
|
+
import { Animated, Easing, Platform } from "react-native";
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
5
|
+
|
|
6
|
+
//#region src/native/atom/skeleton.tsx
|
|
7
|
+
/**
|
|
8
|
+
* A loading placeholder. The same pale surface + pulse as the web base/skeleton.
|
|
9
|
+
*
|
|
10
|
+
* The web uses `animate-pulse` (a CSS animation), but native should not depend on
|
|
11
|
+
* CSS animation support, so `Animated` produces the same 2-second pulse.
|
|
12
|
+
*/
|
|
13
|
+
function Skeleton({ className }) {
|
|
14
|
+
const opacity = useRef(new Animated.Value(1)).current;
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
const useNativeDriver = Platform.OS !== "web";
|
|
17
|
+
const loop = Animated.loop(Animated.sequence([Animated.timing(opacity, {
|
|
18
|
+
toValue: .4,
|
|
19
|
+
duration: 1e3,
|
|
20
|
+
easing: Easing.inOut((value) => Easing.ease(value)),
|
|
21
|
+
useNativeDriver
|
|
22
|
+
}), Animated.timing(opacity, {
|
|
23
|
+
toValue: 1,
|
|
24
|
+
duration: 1e3,
|
|
25
|
+
easing: Easing.inOut((value) => Easing.ease(value)),
|
|
26
|
+
useNativeDriver
|
|
27
|
+
})]));
|
|
28
|
+
loop.start();
|
|
29
|
+
return () => loop.stop();
|
|
30
|
+
}, [opacity]);
|
|
31
|
+
return /* @__PURE__ */ jsx(Animated.View, {
|
|
32
|
+
"aria-hidden": true,
|
|
33
|
+
style: { opacity },
|
|
34
|
+
className: cn("bg-wash rounded-control", className)
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
//#endregion
|
|
39
|
+
export { Skeleton };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { NamedControlA11yProps } from "../lib/control.js";
|
|
2
|
+
import { ReactNode } from "react";
|
|
3
|
+
//#region src/native/atom/slider.d.ts
|
|
4
|
+
export type SliderProps = NamedControlA11yProps & {
|
|
5
|
+
value: number;
|
|
6
|
+
onValueChange: (value: number) => void;
|
|
7
|
+
min?: number;
|
|
8
|
+
max: number;
|
|
9
|
+
step?: number;
|
|
10
|
+
label?: ReactNode;
|
|
11
|
+
required?: boolean;
|
|
12
|
+
description?: ReactNode;
|
|
13
|
+
helpText?: ReactNode;
|
|
14
|
+
disabled?: boolean;
|
|
15
|
+
/** Formatted string shown to the right of the value. Defaults to the raw number. */
|
|
16
|
+
formattedValue?: string;
|
|
17
|
+
/** Name for screen readers. A string `label` is used as-is, so pass this only when `label` is not a string. */
|
|
18
|
+
accessibilityLabel?: string;
|
|
19
|
+
className?: string;
|
|
20
|
+
/** Class for the label text (made destructive when the form has an error). */
|
|
21
|
+
labelClassName?: string;
|
|
22
|
+
wrapperClassName?: string;
|
|
23
|
+
errorSlot?: ReactNode;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* A controlled-only Slider. Same layout as the web atom/slider: a label row with the current value at the right end.
|
|
27
|
+
*
|
|
28
|
+
* The web also accepts a range (`number[]`) to match Radix's internal representation,
|
|
29
|
+
* but `@react-native-community/slider` has a single thumb only, so native handles a single value only.
|
|
30
|
+
*/
|
|
31
|
+
export declare function Slider({ value, onValueChange, min, max, step, label, required, description, helpText, disabled, formattedValue, accessibilityLabel, accessibilityHint, className, labelClassName, wrapperClassName, errorSlot, id, "aria-describedby": ariaDescribedBy, "aria-invalid": ariaInvalid }: SliderProps): import("react").JSX.Element;
|
|
32
|
+
//#endregion
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { useTokenColor } from "../lib/token-color.js";
|
|
2
|
+
import { cn } from "../lib/utils.js";
|
|
3
|
+
import { Text as Text$1 } from "../base/text.js";
|
|
4
|
+
import { tabularNums } from "../lib/typography.js";
|
|
5
|
+
import { Label } from "./label.js";
|
|
6
|
+
import { View } from "react-native";
|
|
7
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
import SliderPrimitive from "@react-native-community/slider";
|
|
9
|
+
|
|
10
|
+
//#region src/native/atom/slider.tsx
|
|
11
|
+
/**
|
|
12
|
+
* A controlled-only Slider. Same layout as the web atom/slider: a label row with the current value at the right end.
|
|
13
|
+
*
|
|
14
|
+
* The web also accepts a range (`number[]`) to match Radix's internal representation,
|
|
15
|
+
* but `@react-native-community/slider` has a single thumb only, so native handles a single value only.
|
|
16
|
+
*/
|
|
17
|
+
function Slider({ value, onValueChange, min = 0, max, step, label, required, description, helpText, disabled, formattedValue, accessibilityLabel, accessibilityHint, className, labelClassName, wrapperClassName, errorSlot, id, "aria-describedby": ariaDescribedBy, "aria-invalid": ariaInvalid }) {
|
|
18
|
+
const action = useTokenColor("--action");
|
|
19
|
+
const track = useTokenColor("--wash");
|
|
20
|
+
return /* @__PURE__ */ jsxs(View, {
|
|
21
|
+
className: cn("gap-2", wrapperClassName),
|
|
22
|
+
children: [
|
|
23
|
+
/* @__PURE__ */ jsxs(View, {
|
|
24
|
+
className: "flex-row items-baseline justify-between gap-2",
|
|
25
|
+
children: [label ? /* @__PURE__ */ jsx(Label, {
|
|
26
|
+
required,
|
|
27
|
+
helpText,
|
|
28
|
+
className: cn("text-xs font-semibold opacity-80", labelClassName),
|
|
29
|
+
children: label
|
|
30
|
+
}) : /* @__PURE__ */ jsx(View, {}), /* @__PURE__ */ jsx(Text$1, {
|
|
31
|
+
style: tabularNums,
|
|
32
|
+
className: "text-muted-foreground font-mono text-sm",
|
|
33
|
+
children: formattedValue ?? String(value)
|
|
34
|
+
})]
|
|
35
|
+
}),
|
|
36
|
+
/* @__PURE__ */ jsx(View, {
|
|
37
|
+
className: cn("grow", className),
|
|
38
|
+
children: /* @__PURE__ */ jsx(SliderPrimitive, {
|
|
39
|
+
value,
|
|
40
|
+
onValueChange,
|
|
41
|
+
minimumValue: min,
|
|
42
|
+
maximumValue: max,
|
|
43
|
+
step: step ?? 0,
|
|
44
|
+
disabled,
|
|
45
|
+
minimumTrackTintColor: action,
|
|
46
|
+
maximumTrackTintColor: track,
|
|
47
|
+
thumbTintColor: action,
|
|
48
|
+
accessibilityLabel: accessibilityLabel ?? (typeof label === "string" ? label : void 0),
|
|
49
|
+
accessibilityHint,
|
|
50
|
+
id,
|
|
51
|
+
"aria-describedby": ariaDescribedBy,
|
|
52
|
+
"aria-invalid": ariaInvalid,
|
|
53
|
+
"aria-valuemin": min,
|
|
54
|
+
"aria-valuemax": max,
|
|
55
|
+
"aria-valuenow": value,
|
|
56
|
+
"aria-valuetext": formattedValue,
|
|
57
|
+
accessibilityValue: {
|
|
58
|
+
min,
|
|
59
|
+
max,
|
|
60
|
+
now: value,
|
|
61
|
+
text: formattedValue
|
|
62
|
+
}
|
|
63
|
+
})
|
|
64
|
+
}),
|
|
65
|
+
description ? /* @__PURE__ */ jsx(Text$1, {
|
|
66
|
+
className: "text-muted-foreground text-xs",
|
|
67
|
+
children: description
|
|
68
|
+
}) : null,
|
|
69
|
+
errorSlot
|
|
70
|
+
]
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
//#endregion
|
|
75
|
+
export { Slider };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
//#region src/native/atom/spinner.d.ts
|
|
2
|
+
export type SpinnerProps = {
|
|
3
|
+
/** Fills the parent and centers the spinner. */
|
|
4
|
+
full?: boolean;
|
|
5
|
+
size?: "small" | "large";
|
|
6
|
+
/** Name for screen readers. Defaults to the "loading" label. */
|
|
7
|
+
label?: string;
|
|
8
|
+
className?: string;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Loading indicator. Its `full` behavior is the same as the web atom/spinner.
|
|
12
|
+
* It looks like the OS-standard spinner (the native counterpart of the web's rotating lucide icon).
|
|
13
|
+
*/
|
|
14
|
+
export declare function Spinner({ full, size, label, className }: SpinnerProps): import("react").JSX.Element;
|
|
15
|
+
//#endregion
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { useTokenColor } from "../lib/token-color.js";
|
|
2
|
+
import { cn } from "../lib/utils.js";
|
|
3
|
+
import { LOADING_LABEL } from "../lib/labels.js";
|
|
4
|
+
import { ActivityIndicator, View } from "react-native";
|
|
5
|
+
import { jsx } from "react/jsx-runtime";
|
|
6
|
+
|
|
7
|
+
//#region src/native/atom/spinner.tsx
|
|
8
|
+
/**
|
|
9
|
+
* Loading indicator. Its `full` behavior is the same as the web atom/spinner.
|
|
10
|
+
* It looks like the OS-standard spinner (the native counterpart of the web's rotating lucide icon).
|
|
11
|
+
*/
|
|
12
|
+
function Spinner({ full, size = "small", label = LOADING_LABEL, className }) {
|
|
13
|
+
const ink = useTokenColor("--ink-1000");
|
|
14
|
+
return /* @__PURE__ */ jsx(View, {
|
|
15
|
+
className: cn(full && "h-full w-full grow items-center justify-center", className),
|
|
16
|
+
children: /* @__PURE__ */ jsx(ActivityIndicator, {
|
|
17
|
+
size,
|
|
18
|
+
color: ink,
|
|
19
|
+
accessibilityLabel: label
|
|
20
|
+
})
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
//#endregion
|
|
25
|
+
export { Spinner };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ControlA11yProps } from "../lib/control.js";
|
|
2
|
+
//#region src/native/atom/switch.d.ts
|
|
3
|
+
export type SwitchProps = ControlA11yProps & {
|
|
4
|
+
checked: boolean;
|
|
5
|
+
onCheckedChange: (checked: boolean) => void;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
/** Name for screen readers. The switch itself has no text, so always pass it when a label is placed next to it. */
|
|
8
|
+
accessibilityLabel?: string;
|
|
9
|
+
className?: string;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* A round switch identical to the web base/switch (on is filled indigo, off is a wash surface with a line-control border).
|
|
13
|
+
*
|
|
14
|
+
* When the OS-standard switch is needed, use the `@expo/ui` one in `base/`. This is
|
|
15
|
+
* an RN implementation that prioritizes looking the same as the web.
|
|
16
|
+
*/
|
|
17
|
+
export declare function Switch({ checked, onCheckedChange, disabled, accessibilityLabel, accessibilityHint, className, id, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, "aria-invalid": ariaInvalid }: SwitchProps): import("react").JSX.Element;
|
|
18
|
+
//#endregion
|