@lt-three/love3 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +86 -2
- 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 +17 -0
- package/dist/native/analytics/multi-line-chart.js +215 -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 +13 -0
- package/dist/native/atom/separator.js +17 -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 +23 -0
- package/dist/native/form/form.js +45 -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 +49 -0
- package/dist/native/lib/confirm.js +70 -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 +17 -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 +12 -0
- package/dist/native/lib/network.js +21 -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 +46 -0
- package/dist/native/lib/snackbar.js +60 -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 +40 -0
- package/dist/web/atom/segmented-control.js +43 -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 +22 -0
- package/dist/web/atom/text-area.js +26 -0
- package/dist/web/atom/text-field.d.ts +17 -0
- package/dist/web/atom/text-field.js +21 -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 +33 -0
- package/dist/web/layout/titled-modal.js +59 -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 +205 -4
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { useTokenColor } from "../lib/token-color.js";
|
|
2
|
+
import { Text as Text$1 } from "../base/text.js";
|
|
3
|
+
import { CLOSE_LABEL } from "../lib/labels.js";
|
|
4
|
+
import { useId } from "react";
|
|
5
|
+
import { Modal as Modal$1, Pressable, ScrollView, StyleSheet, View } from "react-native";
|
|
6
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
import Feather from "@expo/vector-icons/Feather";
|
|
8
|
+
|
|
9
|
+
//#region src/native/layout/modal.tsx
|
|
10
|
+
/**
|
|
11
|
+
* 画面中央に出る確認・編集用のダイアログ。`@lt-three/web` の layout/modal に対応する。
|
|
12
|
+
* 外装は overlay 面(surface 角丸・shadow-lg。枠は付けない)で、本文だけがスクロールする。
|
|
13
|
+
*
|
|
14
|
+
* 見出しがダイアログの名前(`aria-labelledby`)、補足が説明(`aria-describedby`)になる。
|
|
15
|
+
* 役割(`role="dialog"`・`aria-modal`)・フォーカスの閉じ込め・Esc は `Modal` が持つ。
|
|
16
|
+
* web の `layout/modal` は `dialog`(`DialogController`)で開閉を受けるが、native は `open` / `onOpenChange`(移植元のまま)。
|
|
17
|
+
*/
|
|
18
|
+
function Modal({ open, onOpenChange, title, description, content, footer, dismissOnBackdropPress = false, closeLabel = CLOSE_LABEL }) {
|
|
19
|
+
const ink = useTokenColor("--ink-500");
|
|
20
|
+
const id = useId();
|
|
21
|
+
const titleId = `${id}-title`;
|
|
22
|
+
const descriptionId = `${id}-description`;
|
|
23
|
+
return /* @__PURE__ */ jsx(Modal$1, {
|
|
24
|
+
visible: open,
|
|
25
|
+
transparent: true,
|
|
26
|
+
animationType: "fade",
|
|
27
|
+
onRequestClose: () => onOpenChange(false),
|
|
28
|
+
"aria-labelledby": titleId,
|
|
29
|
+
"aria-describedby": description ? descriptionId : void 0,
|
|
30
|
+
children: /* @__PURE__ */ jsxs(View, {
|
|
31
|
+
style: { flex: 1 },
|
|
32
|
+
children: [/* @__PURE__ */ jsx(Pressable, {
|
|
33
|
+
accessible: false,
|
|
34
|
+
style: StyleSheet.absoluteFill,
|
|
35
|
+
className: "bg-scrim",
|
|
36
|
+
onPress: dismissOnBackdropPress ? () => onOpenChange(false) : void 0
|
|
37
|
+
}), /* @__PURE__ */ jsx(View, {
|
|
38
|
+
pointerEvents: "box-none",
|
|
39
|
+
className: "flex-1 items-center justify-center p-6",
|
|
40
|
+
children: /* @__PURE__ */ jsx(View, {
|
|
41
|
+
className: "max-h-[80%] w-full rounded-surface bg-popover shadow-lg",
|
|
42
|
+
children: /* @__PURE__ */ jsxs(View, {
|
|
43
|
+
className: "shrink overflow-hidden rounded-surface",
|
|
44
|
+
children: [
|
|
45
|
+
/* @__PURE__ */ jsxs(View, {
|
|
46
|
+
className: "flex-row items-start justify-between gap-2 border-b border-line px-4 py-3",
|
|
47
|
+
children: [/* @__PURE__ */ jsxs(View, {
|
|
48
|
+
className: "shrink gap-1",
|
|
49
|
+
children: [/* @__PURE__ */ jsx(Text$1, {
|
|
50
|
+
id: titleId,
|
|
51
|
+
role: "heading",
|
|
52
|
+
"aria-level": "2",
|
|
53
|
+
className: "text-base leading-6 font-semibold",
|
|
54
|
+
children: title
|
|
55
|
+
}), description ? /* @__PURE__ */ jsx(Text$1, {
|
|
56
|
+
id: descriptionId,
|
|
57
|
+
className: "text-muted-foreground text-[13px] leading-5",
|
|
58
|
+
children: description
|
|
59
|
+
}) : null]
|
|
60
|
+
}), /* @__PURE__ */ jsx(Pressable, {
|
|
61
|
+
accessibilityRole: "button",
|
|
62
|
+
accessibilityLabel: closeLabel,
|
|
63
|
+
hitSlop: 12,
|
|
64
|
+
onPress: () => onOpenChange(false),
|
|
65
|
+
children: /* @__PURE__ */ jsx(Feather, {
|
|
66
|
+
name: "x",
|
|
67
|
+
size: 16,
|
|
68
|
+
color: ink
|
|
69
|
+
})
|
|
70
|
+
})]
|
|
71
|
+
}),
|
|
72
|
+
/* @__PURE__ */ jsx(ScrollView, {
|
|
73
|
+
style: { flexShrink: 1 },
|
|
74
|
+
contentContainerStyle: {
|
|
75
|
+
gap: 16,
|
|
76
|
+
padding: 16
|
|
77
|
+
},
|
|
78
|
+
children: content
|
|
79
|
+
}),
|
|
80
|
+
footer ? /* @__PURE__ */ jsx(View, {
|
|
81
|
+
className: "flex-row justify-end gap-2 border-t border-line px-4 py-3",
|
|
82
|
+
children: footer
|
|
83
|
+
}) : null
|
|
84
|
+
]
|
|
85
|
+
})
|
|
86
|
+
})
|
|
87
|
+
})]
|
|
88
|
+
})
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
//#endregion
|
|
93
|
+
export { Modal };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
//#region src/native/layout/not-found.d.ts
|
|
2
|
+
export type NotFoundProps = {
|
|
3
|
+
/** 表示文言。共有パッケージなので使用側が持つ。 */
|
|
4
|
+
labels: {
|
|
5
|
+
title: string;
|
|
6
|
+
back: string;
|
|
7
|
+
};
|
|
8
|
+
onBack: () => void;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* 見つからなかった画面。`@lt-three/web` の layout/not-found に対応する。
|
|
12
|
+
*
|
|
13
|
+
* web は `action="previous-page"` で `history.back()` を呼ぶが、native の戻り先は
|
|
14
|
+
* ナビゲーションスタックに依存するので、使用側から `onBack`(`router.back()` 等)を受け取る。
|
|
15
|
+
*/
|
|
16
|
+
export declare function NotFound({ labels, onBack }: NotFoundProps): import("react").JSX.Element;
|
|
17
|
+
//#endregion
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Text as Text$1 } from "../base/text.js";
|
|
2
|
+
import { Button } from "../atom/button.js";
|
|
3
|
+
import { View } from "react-native";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
|
|
6
|
+
//#region src/native/layout/not-found.tsx
|
|
7
|
+
/**
|
|
8
|
+
* 見つからなかった画面。`@lt-three/web` の layout/not-found に対応する。
|
|
9
|
+
*
|
|
10
|
+
* web は `action="previous-page"` で `history.back()` を呼ぶが、native の戻り先は
|
|
11
|
+
* ナビゲーションスタックに依存するので、使用側から `onBack`(`router.back()` 等)を受け取る。
|
|
12
|
+
*/
|
|
13
|
+
function NotFound({ labels, onBack }) {
|
|
14
|
+
return /* @__PURE__ */ jsxs(View, {
|
|
15
|
+
className: "h-full w-full items-center justify-center gap-4 p-6",
|
|
16
|
+
children: [/* @__PURE__ */ jsx(Text$1, {
|
|
17
|
+
className: "text-base font-semibold",
|
|
18
|
+
children: labels.title
|
|
19
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
20
|
+
className: "self-center",
|
|
21
|
+
variant: "outline",
|
|
22
|
+
size: "sm",
|
|
23
|
+
onPress: onBack,
|
|
24
|
+
children: labels.back
|
|
25
|
+
})]
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
//#endregion
|
|
30
|
+
export { NotFound };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
//#region src/native/layout/page-frame.d.ts
|
|
3
|
+
export type PageFrameProps = {
|
|
4
|
+
/** ヘッダの見出し(画面のタイトル。`role="heading"` `aria-level=1`)。 */
|
|
5
|
+
title: string;
|
|
6
|
+
/** ヘッダ右端(戻る・設定・ユーザーなどのボタン)。 */
|
|
7
|
+
trailing?: ReactNode;
|
|
8
|
+
children: ReactNode;
|
|
9
|
+
/** 本文の下のフッタ(著作権・リンクなど)。 */
|
|
10
|
+
footer?: ReactNode;
|
|
11
|
+
/** 下に固定するナビ(`layout/tab-bar`)。本文はこの上でスクロールする。 */
|
|
12
|
+
nav?: ReactNode;
|
|
13
|
+
/** 本文(スクロールする領域)の追加クラス。 */
|
|
14
|
+
contentClassName?: string;
|
|
15
|
+
className?: string;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* 画面の骨組み。`@lt-three/love3/web/layout/page-frame.tsx` に対応する(header・main・footer・nav)。
|
|
19
|
+
* 上にヘッダ(banner)、真ん中にスクロールする本文(main)、その下にフッタ(contentinfo)、最下段にナビ(`TabBar`)。
|
|
20
|
+
* 上端・下端の安全領域はアプリが持つ(外側の `SafeAreaView` か、`className` の `pt-*`)。
|
|
21
|
+
*/
|
|
22
|
+
export declare function PageFrame({ title, trailing, children, footer, nav, contentClassName, className }: PageFrameProps): import("react").JSX.Element;
|
|
23
|
+
//#endregion
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { cn } from "../lib/utils.js";
|
|
2
|
+
import { Text as Text$1 } from "../base/text.js";
|
|
3
|
+
import { ScrollView, View } from "react-native";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
|
|
6
|
+
//#region src/native/layout/page-frame.tsx
|
|
7
|
+
/**
|
|
8
|
+
* 画面の骨組み。`@lt-three/love3/web/layout/page-frame.tsx` に対応する(header・main・footer・nav)。
|
|
9
|
+
* 上にヘッダ(banner)、真ん中にスクロールする本文(main)、その下にフッタ(contentinfo)、最下段にナビ(`TabBar`)。
|
|
10
|
+
* 上端・下端の安全領域はアプリが持つ(外側の `SafeAreaView` か、`className` の `pt-*`)。
|
|
11
|
+
*/
|
|
12
|
+
function PageFrame({ title, trailing, children, footer, nav, contentClassName, className }) {
|
|
13
|
+
return /* @__PURE__ */ jsxs(View, {
|
|
14
|
+
className: cn("bg-background flex-1", className),
|
|
15
|
+
children: [
|
|
16
|
+
/* @__PURE__ */ jsxs(View, {
|
|
17
|
+
role: "banner",
|
|
18
|
+
className: "border-line flex-row items-center justify-between gap-2 border-b px-4 py-3",
|
|
19
|
+
children: [/* @__PURE__ */ jsx(Text$1, {
|
|
20
|
+
role: "heading",
|
|
21
|
+
"aria-level": "1",
|
|
22
|
+
numberOfLines: 2,
|
|
23
|
+
className: "shrink text-lg font-semibold",
|
|
24
|
+
children: title
|
|
25
|
+
}), trailing]
|
|
26
|
+
}),
|
|
27
|
+
/* @__PURE__ */ jsxs(ScrollView, {
|
|
28
|
+
className: "flex-1",
|
|
29
|
+
contentContainerClassName: "gap-4 p-4",
|
|
30
|
+
children: [/* @__PURE__ */ jsx(View, {
|
|
31
|
+
role: "main",
|
|
32
|
+
className: cn("gap-4", contentClassName),
|
|
33
|
+
children
|
|
34
|
+
}), footer ? /* @__PURE__ */ jsx(View, {
|
|
35
|
+
role: "contentinfo",
|
|
36
|
+
className: "border-line border-t pt-4",
|
|
37
|
+
children: footer
|
|
38
|
+
}) : null]
|
|
39
|
+
}),
|
|
40
|
+
nav
|
|
41
|
+
]
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
//#endregion
|
|
46
|
+
export { PageFrame };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
import { ViewStyle } from "react-native";
|
|
3
|
+
//#region src/native/layout/panel.d.ts
|
|
4
|
+
export type PanelProps = {
|
|
5
|
+
children: ReactNode;
|
|
6
|
+
className?: string;
|
|
7
|
+
style?: ViewStyle;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* 内容面。`@lt-three/web` の Card と同じ外装(surface 角丸・1px の極薄の罫線・raised 面。影は付けない)。
|
|
11
|
+
* 内側の余白は使用側が決める。
|
|
12
|
+
*
|
|
13
|
+
* 罫線は `border-border` ではなく `border-line` を使う。`--border` は
|
|
14
|
+
* スタイルシート中で 1 度しか宣言されないため react-native-css がビルド時に
|
|
15
|
+
* 単一値へ畳んでしまい、`.dark` で切り替わらなくなる(`.claude/rules/packages/ts/index.md` 参照)。
|
|
16
|
+
*/
|
|
17
|
+
export declare function Panel({ children, className, style }: PanelProps): import("react").JSX.Element;
|
|
18
|
+
//#endregion
|
|
@@ -0,0 +1,23 @@
|
|
|
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/layout/panel.tsx
|
|
6
|
+
/**
|
|
7
|
+
* 内容面。`@lt-three/web` の Card と同じ外装(surface 角丸・1px の極薄の罫線・raised 面。影は付けない)。
|
|
8
|
+
* 内側の余白は使用側が決める。
|
|
9
|
+
*
|
|
10
|
+
* 罫線は `border-border` ではなく `border-line` を使う。`--border` は
|
|
11
|
+
* スタイルシート中で 1 度しか宣言されないため react-native-css がビルド時に
|
|
12
|
+
* 単一値へ畳んでしまい、`.dark` で切り替わらなくなる(`.claude/rules/packages/ts/index.md` 参照)。
|
|
13
|
+
*/
|
|
14
|
+
function Panel({ children, className, style }) {
|
|
15
|
+
return /* @__PURE__ */ jsx(View, {
|
|
16
|
+
className: cn("overflow-hidden rounded-surface border border-line bg-card", className),
|
|
17
|
+
style,
|
|
18
|
+
children
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
//#endregion
|
|
23
|
+
export { Panel };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { ReactElement, ReactNode } from "react";
|
|
2
|
+
//#region src/native/layout/reorderable-list.d.ts
|
|
3
|
+
export type ReorderableRenderInfo<T> = {
|
|
4
|
+
item: T;
|
|
5
|
+
index: number;
|
|
6
|
+
/**
|
|
7
|
+
* 掴んでドラッグを始める。**行自身の `Pressable` の `onLongPress` に渡すこと。**
|
|
8
|
+
* ラッパーの `Pressable` に付けると、行の内側の `Pressable`(タップで詳細を開く等)が
|
|
9
|
+
* レスポンダを取ってしまい、長押しが外側まで来ない = ドラッグが始まらない。
|
|
10
|
+
*/
|
|
11
|
+
drag: () => void;
|
|
12
|
+
/** その行がいま掴まれているか。掴んだ行は見た目を明確に変えること。 */
|
|
13
|
+
active: boolean;
|
|
14
|
+
};
|
|
15
|
+
export type ReorderableListProps<T> = {
|
|
16
|
+
data: T[];
|
|
17
|
+
keyExtractor: (item: T) => string;
|
|
18
|
+
renderItem: (info: ReorderableRenderInfo<T>) => ReactNode;
|
|
19
|
+
/** 並べ替え後の配列を返す。永続化は使用側が行う。 */
|
|
20
|
+
onReorder: (next: T[]) => void;
|
|
21
|
+
/** false のあいだはドラッグを受け付けない(絞り込み中など)。 */
|
|
22
|
+
dragEnabled?: boolean;
|
|
23
|
+
ListHeaderComponent?: ReactElement | null;
|
|
24
|
+
ListFooterComponent?: ReactElement | null;
|
|
25
|
+
ListEmptyComponent?: ReactElement | null;
|
|
26
|
+
contentContainerClassName?: string;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* 長押しで掴んで並べ替えるリスト。**iOS / Android の同じ実装で動く**。
|
|
30
|
+
*
|
|
31
|
+
* SwiftUI の `List.ForEach onMove` は iOS でしか使えず、放っておくと
|
|
32
|
+
* 「Android だけ並べ替えできない」が生まれる。ここは Reanimated + Gesture Handler の
|
|
33
|
+
* `react-native-reorderable-list` に寄せて、プラットフォームで実装を分けない。
|
|
34
|
+
*
|
|
35
|
+
* **アプリの root に `GestureHandlerRootView` が要る**(Android)。無くても例外は出ず、
|
|
36
|
+
* ドラッグもスワイプも無言で効かなくなる。
|
|
37
|
+
*
|
|
38
|
+
* 並べ替えの確定は `onReorder` の 1 回だけ。ドラッグ中は内部で表示だけ動かすので、
|
|
39
|
+
* 途中経過で API を叩かない。
|
|
40
|
+
*/
|
|
41
|
+
export declare function ReorderableList<T>({ data, keyExtractor, renderItem, onReorder, dragEnabled, ListHeaderComponent, ListFooterComponent, ListEmptyComponent, contentContainerClassName }: ReorderableListProps<T>): import("react").JSX.Element;
|
|
42
|
+
//#endregion
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Fragment, jsx } from "react/jsx-runtime";
|
|
2
|
+
import Reorderable, { reorderItems, useIsActive, useReorderableDrag } from "react-native-reorderable-list";
|
|
3
|
+
|
|
4
|
+
//#region src/native/layout/reorderable-list.tsx
|
|
5
|
+
/**
|
|
6
|
+
* 長押しで掴んで並べ替えるリスト。**iOS / Android の同じ実装で動く**。
|
|
7
|
+
*
|
|
8
|
+
* SwiftUI の `List.ForEach onMove` は iOS でしか使えず、放っておくと
|
|
9
|
+
* 「Android だけ並べ替えできない」が生まれる。ここは Reanimated + Gesture Handler の
|
|
10
|
+
* `react-native-reorderable-list` に寄せて、プラットフォームで実装を分けない。
|
|
11
|
+
*
|
|
12
|
+
* **アプリの root に `GestureHandlerRootView` が要る**(Android)。無くても例外は出ず、
|
|
13
|
+
* ドラッグもスワイプも無言で効かなくなる。
|
|
14
|
+
*
|
|
15
|
+
* 並べ替えの確定は `onReorder` の 1 回だけ。ドラッグ中は内部で表示だけ動かすので、
|
|
16
|
+
* 途中経過で API を叩かない。
|
|
17
|
+
*/
|
|
18
|
+
function ReorderableList({ data, keyExtractor, renderItem, onReorder, dragEnabled = true, ListHeaderComponent, ListFooterComponent, ListEmptyComponent, contentContainerClassName }) {
|
|
19
|
+
return /* @__PURE__ */ jsx(Reorderable, {
|
|
20
|
+
data,
|
|
21
|
+
keyExtractor: (item) => keyExtractor(item),
|
|
22
|
+
renderItem: ({ item, index }) => /* @__PURE__ */ jsx(Cell, {
|
|
23
|
+
item,
|
|
24
|
+
index,
|
|
25
|
+
render: renderItem
|
|
26
|
+
}),
|
|
27
|
+
onReorder: ({ from, to }) => onReorder(reorderItems(data, from, to)),
|
|
28
|
+
dragEnabled,
|
|
29
|
+
shouldUpdateActiveItem: true,
|
|
30
|
+
ListHeaderComponent: ListHeaderComponent ?? void 0,
|
|
31
|
+
ListFooterComponent: ListFooterComponent ?? void 0,
|
|
32
|
+
ListEmptyComponent: ListEmptyComponent ?? void 0,
|
|
33
|
+
contentContainerClassName
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* 行の描画。`useReorderableDrag` / `useIsActive` は**リストの item の中でしか呼べない**ので、
|
|
38
|
+
* ここで呼んで使用側へ渡す。
|
|
39
|
+
*/
|
|
40
|
+
function Cell({ item, index, render }) {
|
|
41
|
+
const drag = useReorderableDrag();
|
|
42
|
+
const active = useIsActive();
|
|
43
|
+
return /* @__PURE__ */ jsx(Fragment, { children: render({
|
|
44
|
+
item,
|
|
45
|
+
index,
|
|
46
|
+
drag,
|
|
47
|
+
active
|
|
48
|
+
}) });
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
//#endregion
|
|
52
|
+
export { ReorderableList };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
//#region src/native/layout/sheet.d.ts
|
|
3
|
+
export type SheetProps = {
|
|
4
|
+
open: boolean;
|
|
5
|
+
onOpenChange: (open: boolean) => void;
|
|
6
|
+
/** 見出し。ダイアログの名前になる(名前の無いダイアログにしないため、移植元と違って必須。web の `layout/sheet` と同じ)。 */
|
|
7
|
+
title: ReactNode;
|
|
8
|
+
description?: ReactNode;
|
|
9
|
+
content: ReactNode;
|
|
10
|
+
footer?: ReactNode;
|
|
11
|
+
/** 背面タップで閉じるか(既定 true)。 */
|
|
12
|
+
dismissOnBackdropPress?: boolean;
|
|
13
|
+
/** 閉じるボタンの読み上げ名(既定は「閉じる」)。 */
|
|
14
|
+
closeLabel?: string;
|
|
15
|
+
/** 中身に余白を敷くか(既定 true)。端まで敷き詰める行リストでは false。 */
|
|
16
|
+
padded?: boolean;
|
|
17
|
+
/** 画面高に対する最大の高さ(既定 0.85)。 */
|
|
18
|
+
maxHeightRatio?: number;
|
|
19
|
+
/** 閉じ切った後に呼ばれる。**次のシートを開くときはここで開くこと**(`base/sheet` 参照)。 */
|
|
20
|
+
onClosed?: () => void;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* 下から出るシート。`@lt-three/web` の layout/sheet(画面端から出るパネル)に対応する。
|
|
24
|
+
* native では端ではなく下から出すのが標準の作法なので、位置だけ読み替えている(web の `side` は持たない)。
|
|
25
|
+
*
|
|
26
|
+
* 面の出し方・スクリム・safe-area・キーボード回避は `base/sheet` が持つ。
|
|
27
|
+
* 見出しがダイアログの名前(`aria-labelledby`)、補足が説明(`aria-describedby`)になる。
|
|
28
|
+
*/
|
|
29
|
+
export declare function Sheet({ open, onOpenChange, title, description, content, footer, dismissOnBackdropPress, closeLabel, padded, maxHeightRatio, onClosed }: SheetProps): import("react").JSX.Element;
|
|
30
|
+
//#endregion
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { isBlankNode } from "../lib/utils.js";
|
|
2
|
+
import { SheetFooter, SheetHeader, SheetScroll, SheetShell } from "../base/sheet.js";
|
|
3
|
+
import { useId } from "react";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
|
|
6
|
+
//#region src/native/layout/sheet.tsx
|
|
7
|
+
/**
|
|
8
|
+
* 下から出るシート。`@lt-three/web` の layout/sheet(画面端から出るパネル)に対応する。
|
|
9
|
+
* native では端ではなく下から出すのが標準の作法なので、位置だけ読み替えている(web の `side` は持たない)。
|
|
10
|
+
*
|
|
11
|
+
* 面の出し方・スクリム・safe-area・キーボード回避は `base/sheet` が持つ。
|
|
12
|
+
* 見出しがダイアログの名前(`aria-labelledby`)、補足が説明(`aria-describedby`)になる。
|
|
13
|
+
*/
|
|
14
|
+
function Sheet({ open, onOpenChange, title, description, content, footer, dismissOnBackdropPress = true, closeLabel, padded = true, maxHeightRatio = .85, onClosed }) {
|
|
15
|
+
const id = useId();
|
|
16
|
+
const titleId = `${id}-title`;
|
|
17
|
+
const descriptionId = `${id}-description`;
|
|
18
|
+
return /* @__PURE__ */ jsxs(SheetShell, {
|
|
19
|
+
open,
|
|
20
|
+
onOpenChange,
|
|
21
|
+
dismissOnBackdropPress,
|
|
22
|
+
maxHeightRatio,
|
|
23
|
+
onClosed,
|
|
24
|
+
"aria-labelledby": isBlankNode(title) ? void 0 : titleId,
|
|
25
|
+
"aria-describedby": isBlankNode(description) ? void 0 : descriptionId,
|
|
26
|
+
children: [
|
|
27
|
+
/* @__PURE__ */ jsx(SheetHeader, {
|
|
28
|
+
title,
|
|
29
|
+
description,
|
|
30
|
+
closeLabel,
|
|
31
|
+
onClose: () => onOpenChange(false),
|
|
32
|
+
titleId,
|
|
33
|
+
descriptionId
|
|
34
|
+
}),
|
|
35
|
+
/* @__PURE__ */ jsx(SheetScroll, {
|
|
36
|
+
padded,
|
|
37
|
+
hasFooter: !!footer,
|
|
38
|
+
children: content
|
|
39
|
+
}),
|
|
40
|
+
footer ? /* @__PURE__ */ jsx(SheetFooter, { children: footer }) : null
|
|
41
|
+
]
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
//#endregion
|
|
46
|
+
export { Sheet };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
//#region src/native/layout/simple-dialog.d.ts
|
|
3
|
+
export type SimpleDialogProps = {
|
|
4
|
+
open: boolean;
|
|
5
|
+
onOpenChange: (open: boolean) => void;
|
|
6
|
+
title: ReactNode;
|
|
7
|
+
children: ReactNode;
|
|
8
|
+
/** 閉じるボタンの読み上げ名(既定は「閉じる」)。 */
|
|
9
|
+
closeLabel?: string;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* タイトルと本文だけの軽量なダイアログ。`@lt-three/web` の layout/simple-dialog に対応する。
|
|
13
|
+
* フッターや説明が要るなら `Modal` を直接使う。
|
|
14
|
+
*/
|
|
15
|
+
export declare function SimpleDialog({ open, onOpenChange, title, children, closeLabel }: SimpleDialogProps): import("react").JSX.Element;
|
|
16
|
+
//#endregion
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Modal } from "./modal.js";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
|
|
4
|
+
//#region src/native/layout/simple-dialog.tsx
|
|
5
|
+
/**
|
|
6
|
+
* タイトルと本文だけの軽量なダイアログ。`@lt-three/web` の layout/simple-dialog に対応する。
|
|
7
|
+
* フッターや説明が要るなら `Modal` を直接使う。
|
|
8
|
+
*/
|
|
9
|
+
function SimpleDialog({ open, onOpenChange, title, children, closeLabel }) {
|
|
10
|
+
return /* @__PURE__ */ jsx(Modal, {
|
|
11
|
+
open,
|
|
12
|
+
onOpenChange,
|
|
13
|
+
title,
|
|
14
|
+
content: children,
|
|
15
|
+
closeLabel
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
//#endregion
|
|
20
|
+
export { SimpleDialog };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { Breakpoint } from "../lib/breakpoints.js";
|
|
2
|
+
import { ReactNode } from "react";
|
|
3
|
+
//#region src/native/layout/simple-table.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* 宣言的な薄い罫線のデータテーブル。columns / data を渡すだけで使える。
|
|
6
|
+
* `@lt-three/web` の layout/simple-table と同じ列定義・同じ名前の props(`onRowClick`・`hideBelow`)を取る。
|
|
7
|
+
*
|
|
8
|
+
* ヘッダは frame の淡い面、行罫線は 1px の極薄の線。
|
|
9
|
+
* 数値列は mono + タブラー + 右寄せにする。
|
|
10
|
+
*/
|
|
11
|
+
export type SimpleColumn<T> = {
|
|
12
|
+
/** 列キー(行内で一意)。 */
|
|
13
|
+
key: string;
|
|
14
|
+
header: ReactNode;
|
|
15
|
+
/** セル / ヘッダの揃え(既定 left)。 */
|
|
16
|
+
align?: "left" | "right" | "center";
|
|
17
|
+
/** 等幅 + タブラー(数値・ID 向け)。 */
|
|
18
|
+
mono?: boolean;
|
|
19
|
+
/** 強調(font-medium)。 */
|
|
20
|
+
strong?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* この幅(Tailwind と同じブレークポイント: sm 640・md 768・lg 1024 px。**画面の幅**で見る)より狭いときは列ごと隠す。
|
|
23
|
+
* 狭い画面で重要でない列(ID・補足など)を畳む(web の `hideBelow` と同じ)。未指定なら常に出す。
|
|
24
|
+
*/
|
|
25
|
+
hideBelow?: Breakpoint;
|
|
26
|
+
/** 列幅(px)。省略時は等分。 */
|
|
27
|
+
width?: number;
|
|
28
|
+
/** セル(View)の追加クラス。 */
|
|
29
|
+
cellClassName?: string;
|
|
30
|
+
/** ヘッダのセル(View)の追加クラス。 */
|
|
31
|
+
headClassName?: string;
|
|
32
|
+
/** セルの描画。未指定時は row[key] を表示する。 */
|
|
33
|
+
render?: (row: T) => ReactNode;
|
|
34
|
+
};
|
|
35
|
+
export type SimpleTableProps<T> = {
|
|
36
|
+
columns: SimpleColumn<T>[];
|
|
37
|
+
data: T[];
|
|
38
|
+
/** 行キーの導出。未指定時は index を使う。 */
|
|
39
|
+
getRowKey?: (row: T, index: number) => string;
|
|
40
|
+
/**
|
|
41
|
+
* 行を押す(web の `onRowClick` と同じ名前)。渡すと各行がボタン(フォーカスでき、Enter・Space でも押せる)になり、
|
|
42
|
+
* フォーカスは不透明の outline で示す。
|
|
43
|
+
*/
|
|
44
|
+
onRowClick?: (row: T) => void;
|
|
45
|
+
className?: string;
|
|
46
|
+
/** 列が画面幅に収まらないとき横スクロールさせる。 */
|
|
47
|
+
horizontalScroll?: boolean;
|
|
48
|
+
};
|
|
49
|
+
export declare function SimpleTable<T extends object>({ columns: allColumns, data, getRowKey, onRowClick, className, horizontalScroll }: SimpleTableProps<T>): import("react").JSX.Element;
|
|
50
|
+
//#endregion
|
|
@@ -0,0 +1,75 @@
|
|
|
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 { isShownAtWidth } from "../lib/breakpoints.js";
|
|
5
|
+
import { isValidElement } from "react";
|
|
6
|
+
import { Pressable, ScrollView, View, useWindowDimensions } from "react-native";
|
|
7
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
|
|
9
|
+
//#region src/native/layout/simple-table.tsx
|
|
10
|
+
const alignClass = {
|
|
11
|
+
left: "text-left",
|
|
12
|
+
right: "text-right",
|
|
13
|
+
center: "text-center"
|
|
14
|
+
};
|
|
15
|
+
const justifyClass = {
|
|
16
|
+
left: "justify-start",
|
|
17
|
+
right: "justify-end",
|
|
18
|
+
center: "justify-center"
|
|
19
|
+
};
|
|
20
|
+
/** `render` が無い列の既定の描画。行の `key` の値が、文字・数値・要素のときだけ表示する。 */
|
|
21
|
+
function cellValue(row, key) {
|
|
22
|
+
const value = Reflect.get(row, key);
|
|
23
|
+
if (typeof value === "string" || typeof value === "number" || isValidElement(value)) return value;
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
function SimpleTable({ columns: allColumns, data, getRowKey, onRowClick, className, horizontalScroll }) {
|
|
27
|
+
const { width: screenWidth } = useWindowDimensions();
|
|
28
|
+
const columns = allColumns.filter((col) => isShownAtWidth(col.hideBelow, screenWidth));
|
|
29
|
+
const table = /* @__PURE__ */ jsxs(View, {
|
|
30
|
+
className: cn(!horizontalScroll && "w-full", className),
|
|
31
|
+
children: [/* @__PURE__ */ jsx(View, {
|
|
32
|
+
className: "flex-row border-b border-line bg-frame",
|
|
33
|
+
children: columns.map((col) => /* @__PURE__ */ jsx(View, {
|
|
34
|
+
style: col.width ? { width: col.width } : void 0,
|
|
35
|
+
className: cn("px-2 py-2", !col.width && "flex-1", justifyClass[col.align ?? "left"], col.headClassName),
|
|
36
|
+
children: typeof col.header === "string" || typeof col.header === "number" ? /* @__PURE__ */ jsx(Text$1, {
|
|
37
|
+
className: cn("text-muted-foreground text-xs font-medium", alignClass[col.align ?? "left"]),
|
|
38
|
+
children: col.header
|
|
39
|
+
}) : col.header
|
|
40
|
+
}, col.key))
|
|
41
|
+
}), data.map((row, index) => {
|
|
42
|
+
const content = /* @__PURE__ */ jsx(View, {
|
|
43
|
+
className: "flex-row border-b border-line",
|
|
44
|
+
children: columns.map((col) => {
|
|
45
|
+
const cell = col.render ? col.render(row) : cellValue(row, col.key);
|
|
46
|
+
return /* @__PURE__ */ jsx(View, {
|
|
47
|
+
style: col.width ? { width: col.width } : void 0,
|
|
48
|
+
className: cn("px-2 py-2.5", !col.width && "flex-1", justifyClass[col.align ?? "left"], col.cellClassName),
|
|
49
|
+
children: typeof cell === "string" || typeof cell === "number" ? /* @__PURE__ */ jsx(Text$1, {
|
|
50
|
+
style: col.mono ? tabularNums : void 0,
|
|
51
|
+
className: cn("text-sm", alignClass[col.align ?? "left"], col.mono && "font-mono", col.strong && "text-foreground font-medium"),
|
|
52
|
+
children: cell
|
|
53
|
+
}) : cell
|
|
54
|
+
}, col.key);
|
|
55
|
+
})
|
|
56
|
+
});
|
|
57
|
+
const key = getRowKey ? getRowKey(row, index) : String(index);
|
|
58
|
+
return onRowClick ? /* @__PURE__ */ jsx(Pressable, {
|
|
59
|
+
accessibilityRole: "button",
|
|
60
|
+
onPress: () => onRowClick(row),
|
|
61
|
+
className: "focus:outline-ring focus:outline-2 focus:-outline-offset-2",
|
|
62
|
+
children: content
|
|
63
|
+
}, key) : /* @__PURE__ */ jsx(View, { children: content }, key);
|
|
64
|
+
})]
|
|
65
|
+
});
|
|
66
|
+
if (!horizontalScroll) return table;
|
|
67
|
+
return /* @__PURE__ */ jsx(ScrollView, {
|
|
68
|
+
horizontal: true,
|
|
69
|
+
showsHorizontalScrollIndicator: false,
|
|
70
|
+
children: table
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
//#endregion
|
|
75
|
+
export { SimpleTable };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
//#region src/native/layout/tab-bar.d.ts
|
|
3
|
+
export type TabBarItem = {
|
|
4
|
+
/** 選択値(一意)。 */
|
|
5
|
+
value: string;
|
|
6
|
+
/** 文字のラベル。アイコンだけにしない(読み上げ名・分かりやすさのため)。 */
|
|
7
|
+
label: string;
|
|
8
|
+
/**
|
|
9
|
+
* アイコン。選択状態に合う色(`color`)を渡すので、`Symbol` の `tintColor` などに使う。
|
|
10
|
+
* 文字だけで足りるなら省く。
|
|
11
|
+
*/
|
|
12
|
+
icon?: (state: {
|
|
13
|
+
active: boolean;
|
|
14
|
+
color: string;
|
|
15
|
+
}) => ReactNode;
|
|
16
|
+
};
|
|
17
|
+
export type TabBarProps = {
|
|
18
|
+
items: readonly TabBarItem[];
|
|
19
|
+
/** 選択中の値。 */
|
|
20
|
+
value: string;
|
|
21
|
+
onValueChange: (value: string) => void;
|
|
22
|
+
/** 読み上げ名(ランドマークが複数あるとき区別する)。既定は「メイン」。 */
|
|
23
|
+
accessibilityLabel?: string;
|
|
24
|
+
className?: string;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* 画面の下に置く、トップレベルの行き先の切り替え(3〜5 件)。`layout/tabs`(本文を切り替える下線タブ)とは別物。
|
|
28
|
+
* 選択中は `text-action-ink`(暗い面でも AA)で、選択状態は色だけにせず太さ(`font-semibold`)でも示す。
|
|
29
|
+
* 1 件の押す範囲は高さ 56px 以上(実機の 44pt 基準を上回る)。**下端の安全領域(ホームインジケータ)はアプリが持つ**
|
|
30
|
+
* (`className` に `pb-*` を渡すか、外側の `SafeAreaView` に置く)。
|
|
31
|
+
*/
|
|
32
|
+
export declare function TabBar({ items, value, onValueChange, accessibilityLabel, className }: TabBarProps): import("react").JSX.Element;
|
|
33
|
+
//#endregion
|