@ankhorage/zora 14.0.0 → 15.0.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/CHANGELOG.md +12 -0
- package/README.md +176 -6
- package/dist/features/app-bar/adapters/inbound/AppBar.d.ts +5 -0
- package/dist/features/app-bar/adapters/inbound/AppBar.d.ts.map +1 -0
- package/dist/features/app-bar/adapters/inbound/AppBar.js +92 -0
- package/dist/features/app-bar/adapters/inbound/AppBar.js.map +1 -0
- package/dist/{components/app-bar/meta.d.ts → features/app-bar/appBarMeta.d.ts} +1 -1
- package/dist/features/app-bar/appBarMeta.d.ts.map +1 -0
- package/dist/{components/app-bar/meta.js → features/app-bar/appBarMeta.js} +1 -1
- package/dist/features/app-bar/appBarMeta.js.map +1 -0
- package/dist/features/app-bar/public.d.ts +3 -0
- package/dist/features/app-bar/public.d.ts.map +1 -0
- package/dist/features/app-bar/public.js +2 -0
- package/dist/features/app-bar/public.js.map +1 -0
- package/dist/features/bottom-sheet/public.d.ts +2 -2
- package/dist/features/bottom-sheet/public.d.ts.map +1 -1
- package/dist/features/bottom-sheet/public.js +1 -1
- package/dist/features/bottom-sheet/public.js.map +1 -1
- package/dist/features/breadcrumbs/adapters/inbound/Breadcrumbs.d.ts +5 -0
- package/dist/features/breadcrumbs/adapters/inbound/Breadcrumbs.d.ts.map +1 -0
- package/dist/features/breadcrumbs/adapters/inbound/Breadcrumbs.js +81 -0
- package/dist/features/breadcrumbs/adapters/inbound/Breadcrumbs.js.map +1 -0
- package/dist/features/breadcrumbs/breadcrumbsMeta.d.ts +119 -0
- package/dist/features/breadcrumbs/breadcrumbsMeta.d.ts.map +1 -0
- package/dist/features/breadcrumbs/breadcrumbsMeta.js +94 -0
- package/dist/features/breadcrumbs/breadcrumbsMeta.js.map +1 -0
- package/dist/features/breadcrumbs/public.d.ts +3 -0
- package/dist/features/breadcrumbs/public.d.ts.map +1 -0
- package/dist/features/breadcrumbs/public.js +2 -0
- package/dist/features/breadcrumbs/public.js.map +1 -0
- package/dist/features/button/utils/resolveButtonThemeRecipe.d.ts +1 -1
- package/dist/features/data-table/adapters/inbound/DataTable.d.ts.map +1 -1
- package/dist/features/data-table/adapters/inbound/DataTable.js +4 -2
- package/dist/features/data-table/adapters/inbound/DataTable.js.map +1 -1
- package/dist/features/form/formFieldMeta.d.ts +1 -1
- package/dist/features/form/formFieldMeta.js +1 -1
- package/dist/features/form/formFieldMeta.js.map +1 -1
- package/dist/features/form/radio/utils/resolveRadioGroupThemeRecipe.d.ts +1 -1
- package/dist/features/form/select/adapters/inbound/Select.d.ts +2 -0
- package/dist/features/form/select/adapters/inbound/Select.d.ts.map +1 -0
- package/dist/features/form/select/adapters/inbound/Select.js +2 -0
- package/dist/features/form/select/adapters/inbound/Select.js.map +1 -0
- package/dist/features/form/select/adapters/inbound/Select.native.d.ts +5 -0
- package/dist/features/form/select/adapters/inbound/Select.native.d.ts.map +1 -0
- package/dist/features/form/select/adapters/inbound/Select.native.js +42 -0
- package/dist/features/form/select/adapters/inbound/Select.native.js.map +1 -0
- package/dist/features/form/select/adapters/inbound/Select.web.d.ts +5 -0
- package/dist/features/form/select/adapters/inbound/Select.web.d.ts.map +1 -0
- package/dist/features/form/select/adapters/inbound/Select.web.js +31 -0
- package/dist/features/form/select/adapters/inbound/Select.web.js.map +1 -0
- package/dist/features/form/select/composition/SelectField.d.ts +10 -0
- package/dist/features/form/select/composition/SelectField.d.ts.map +1 -0
- package/dist/features/form/select/composition/SelectField.js +8 -0
- package/dist/features/form/select/composition/SelectField.js.map +1 -0
- package/dist/features/form/select/composition/SelectOptionRow.d.ts +12 -0
- package/dist/features/form/select/composition/SelectOptionRow.d.ts.map +1 -0
- package/dist/features/form/select/composition/SelectOptionRow.js +9 -0
- package/dist/features/form/select/composition/SelectOptionRow.js.map +1 -0
- package/dist/features/form/select/composition/SelectTrigger.d.ts +10 -0
- package/dist/features/form/select/composition/SelectTrigger.d.ts.map +1 -0
- package/dist/features/form/select/composition/SelectTrigger.js +9 -0
- package/dist/features/form/select/composition/SelectTrigger.js.map +1 -0
- package/dist/features/form/select/composition/useSelectController.d.ts +8 -0
- package/dist/features/form/select/composition/useSelectController.d.ts.map +1 -0
- package/dist/features/form/select/composition/useSelectController.js +15 -0
- package/dist/features/form/select/composition/useSelectController.js.map +1 -0
- package/dist/features/form/select/public.d.ts +3 -0
- package/dist/features/form/select/public.d.ts.map +1 -0
- package/dist/features/form/select/public.js +2 -0
- package/dist/features/form/select/public.js.map +1 -0
- package/dist/features/form/select/selectMeta.d.ts +195 -0
- package/dist/features/form/select/selectMeta.d.ts.map +1 -0
- package/dist/features/form/select/selectMeta.js +152 -0
- package/dist/features/form/select/selectMeta.js.map +1 -0
- package/dist/features/popover-menu/adapters/inbound/PopoverMenu.d.ts +5 -0
- package/dist/features/popover-menu/adapters/inbound/PopoverMenu.d.ts.map +1 -0
- package/dist/features/popover-menu/adapters/inbound/PopoverMenu.js +43 -0
- package/dist/features/popover-menu/adapters/inbound/PopoverMenu.js.map +1 -0
- package/dist/features/popover-menu/popoverMenuMeta.d.ts +9 -0
- package/dist/features/popover-menu/popoverMenuMeta.d.ts.map +1 -0
- package/dist/features/popover-menu/popoverMenuMeta.js +9 -0
- package/dist/features/popover-menu/popoverMenuMeta.js.map +1 -0
- package/dist/features/popover-menu/public.d.ts +3 -0
- package/dist/features/popover-menu/public.d.ts.map +1 -0
- package/dist/features/popover-menu/public.js +2 -0
- package/dist/features/popover-menu/public.js.map +1 -0
- package/dist/features/typography/utils/resolveHeadingThemeRecipe.d.ts +1 -1
- package/dist/features/typography/utils/resolveTextThemeRecipe.d.ts +1 -1
- package/dist/index.d.ts +5 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/dist/layout/settings-layout/SettingsLayout.d.ts +0 -2
- package/dist/layout/settings-layout/SettingsLayout.d.ts.map +1 -1
- package/dist/layout/settings-layout/SettingsLayout.js +1 -3
- package/dist/layout/settings-layout/SettingsLayout.js.map +1 -1
- package/dist/metadata/bindableComponentMeta.d.ts +1 -2
- package/dist/metadata/bindableComponentMeta.d.ts.map +1 -1
- package/dist/metadata/bindableComponentMeta.js +1 -2
- package/dist/metadata/bindableComponentMeta.js.map +1 -1
- package/dist/metadata/componentMeta.d.ts.map +1 -1
- package/dist/metadata/componentMeta.js +5 -6
- package/dist/metadata/componentMeta.js.map +1 -1
- package/dist/patterns/reader/ReaderSurface.js +1 -1
- package/dist/patterns/reader/ReaderSurface.js.map +1 -1
- package/dist/patterns/theme-composer/ThemeComposer.js +1 -1
- package/dist/patterns/theme-composer/ThemeComposer.js.map +1 -1
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +5 -6
- package/dist/registry.js.map +1 -1
- package/dist/{components/app-bar/types.d.ts → types/app-bar.d.ts} +8 -5
- package/dist/types/app-bar.d.ts.map +1 -0
- package/dist/types/app-bar.js +2 -0
- package/dist/types/app-bar.js.map +1 -0
- package/dist/{components/breadcrumbs/types.d.ts → types/breadcrumbs.d.ts} +8 -6
- package/dist/types/breadcrumbs.d.ts.map +1 -0
- package/dist/types/breadcrumbs.js +2 -0
- package/dist/types/breadcrumbs.js.map +1 -0
- package/dist/types/data-table.d.ts +2 -2
- package/dist/types/data-table.d.ts.map +1 -1
- package/dist/types/data-table.js.map +1 -1
- package/dist/types/popover-menu.d.ts +24 -0
- package/dist/types/popover-menu.d.ts.map +1 -0
- package/dist/types/popover-menu.js +2 -0
- package/dist/types/popover-menu.js.map +1 -0
- package/dist/types/select.d.ts +22 -0
- package/dist/types/select.d.ts.map +1 -0
- package/dist/types/select.js +2 -0
- package/dist/types/select.js.map +1 -0
- package/package.json +2 -4
- package/src/features/app-bar/adapters/inbound/AppBar.tsx +184 -0
- package/src/features/app-bar/public.ts +2 -0
- package/src/features/bottom-sheet/public.test.ts +10 -1
- package/src/features/bottom-sheet/public.ts +9 -1
- package/src/features/breadcrumbs/adapters/inbound/Breadcrumbs.tsx +179 -0
- package/src/features/breadcrumbs/breadcrumbsMeta.ts +95 -0
- package/src/features/breadcrumbs/public.test.ts +22 -0
- package/src/features/breadcrumbs/public.ts +6 -0
- package/src/features/data-table/adapters/inbound/DataTable.tsx +9 -5
- package/src/features/form/formFieldMeta.ts +1 -1
- package/src/features/form/select/adapters/inbound/Select.native.tsx +78 -0
- package/src/features/form/select/adapters/inbound/Select.tsx +1 -0
- package/src/features/form/select/adapters/inbound/Select.web.tsx +63 -0
- package/src/features/form/select/composition/SelectField.tsx +27 -0
- package/src/features/form/select/composition/SelectOptionRow.tsx +36 -0
- package/src/features/form/select/composition/SelectTrigger.tsx +32 -0
- package/src/features/form/select/composition/useSelectController.ts +21 -0
- package/src/features/form/select/public.test.ts +25 -0
- package/src/features/form/select/public.ts +2 -0
- package/src/features/form/select/selectMeta.ts +154 -0
- package/src/features/popover-menu/adapters/inbound/PopoverMenu.tsx +60 -0
- package/src/{components/breadcrumbs/meta.ts → features/popover-menu/popoverMenuMeta.ts} +3 -3
- package/src/features/popover-menu/public.test.ts +11 -0
- package/src/features/popover-menu/public.ts +6 -0
- package/src/index.ts +15 -8
- package/src/interactionPolicy.test.ts +24 -22
- package/src/layout/settings-layout/SettingsLayout.tsx +1 -3
- package/src/metadata/bindableComponentMeta.test.ts +8 -0
- package/src/metadata/bindableComponentMeta.ts +1 -2
- package/src/metadata/componentMeta.test.ts +3 -0
- package/src/metadata/componentMeta.ts +5 -6
- package/src/nativePeerContract.test.ts +5 -19
- package/src/patterns/reader/ReaderSurface.tsx +1 -1
- package/src/patterns/theme-composer/ThemeComposer.tsx +1 -1
- package/src/platformAcceptance.test.ts +1 -1
- package/src/registry.ts +5 -6
- package/src/theme/themeScopeStructure.test.ts +10 -5
- package/src/{components/app-bar/types.ts → types/app-bar.ts} +7 -4
- package/src/{components/breadcrumbs/types.ts → types/breadcrumbs.ts} +8 -5
- package/src/types/data-table.ts +2 -2
- package/src/types/popover-menu.ts +31 -0
- package/src/{components/select/types.ts → types/select.ts} +11 -3
- package/dist/components/app-bar/AppBar.d.ts +0 -7
- package/dist/components/app-bar/AppBar.d.ts.map +0 -1
- package/dist/components/app-bar/AppBar.js +0 -67
- package/dist/components/app-bar/AppBar.js.map +0 -1
- package/dist/components/app-bar/index.d.ts +0 -3
- package/dist/components/app-bar/index.d.ts.map +0 -1
- package/dist/components/app-bar/index.js +0 -3
- package/dist/components/app-bar/index.js.map +0 -1
- package/dist/components/app-bar/meta.d.ts.map +0 -1
- package/dist/components/app-bar/meta.js.map +0 -1
- package/dist/components/app-bar/types.d.ts.map +0 -1
- package/dist/components/app-bar/types.js +0 -2
- package/dist/components/app-bar/types.js.map +0 -1
- package/dist/components/breadcrumbs/Breadcrumbs.d.ts +0 -7
- package/dist/components/breadcrumbs/Breadcrumbs.d.ts.map +0 -1
- package/dist/components/breadcrumbs/Breadcrumbs.js +0 -80
- package/dist/components/breadcrumbs/Breadcrumbs.js.map +0 -1
- package/dist/components/breadcrumbs/index.d.ts +0 -3
- package/dist/components/breadcrumbs/index.d.ts.map +0 -1
- package/dist/components/breadcrumbs/index.js +0 -2
- package/dist/components/breadcrumbs/index.js.map +0 -1
- package/dist/components/breadcrumbs/meta.d.ts +0 -9
- package/dist/components/breadcrumbs/meta.d.ts.map +0 -1
- package/dist/components/breadcrumbs/meta.js +0 -9
- package/dist/components/breadcrumbs/meta.js.map +0 -1
- package/dist/components/breadcrumbs/types.d.ts.map +0 -1
- package/dist/components/breadcrumbs/types.js +0 -2
- package/dist/components/breadcrumbs/types.js.map +0 -1
- package/dist/components/menu/DropdownMenu.d.ts +0 -7
- package/dist/components/menu/DropdownMenu.d.ts.map +0 -1
- package/dist/components/menu/DropdownMenu.js +0 -9
- package/dist/components/menu/DropdownMenu.js.map +0 -1
- package/dist/components/menu/Menu.d.ts +0 -7
- package/dist/components/menu/Menu.d.ts.map +0 -1
- package/dist/components/menu/Menu.js +0 -46
- package/dist/components/menu/Menu.js.map +0 -1
- package/dist/components/menu/index.d.ts +0 -4
- package/dist/components/menu/index.d.ts.map +0 -1
- package/dist/components/menu/index.js +0 -3
- package/dist/components/menu/index.js.map +0 -1
- package/dist/components/menu/meta.d.ts +0 -17
- package/dist/components/menu/meta.d.ts.map +0 -1
- package/dist/components/menu/meta.js +0 -17
- package/dist/components/menu/meta.js.map +0 -1
- package/dist/components/menu/types.d.ts +0 -22
- package/dist/components/menu/types.d.ts.map +0 -1
- package/dist/components/menu/types.js +0 -2
- package/dist/components/menu/types.js.map +0 -1
- package/dist/components/select/Select.d.ts +0 -7
- package/dist/components/select/Select.d.ts.map +0 -1
- package/dist/components/select/Select.js +0 -32
- package/dist/components/select/Select.js.map +0 -1
- package/dist/components/select/index.d.ts +0 -3
- package/dist/components/select/index.d.ts.map +0 -1
- package/dist/components/select/index.js +0 -3
- package/dist/components/select/index.js.map +0 -1
- package/dist/components/select/meta.d.ts +0 -9
- package/dist/components/select/meta.d.ts.map +0 -1
- package/dist/components/select/meta.js +0 -9
- package/dist/components/select/meta.js.map +0 -1
- package/dist/components/select/types.d.ts +0 -14
- package/dist/components/select/types.d.ts.map +0 -1
- package/dist/components/select/types.js +0 -2
- package/dist/components/select/types.js.map +0 -1
- package/src/components/app-bar/AppBar.tsx +0 -140
- package/src/components/app-bar/index.ts +0 -2
- package/src/components/breadcrumbs/Breadcrumbs.tsx +0 -147
- package/src/components/breadcrumbs/index.ts +0 -2
- package/src/components/menu/DropdownMenu.tsx +0 -11
- package/src/components/menu/Menu.tsx +0 -59
- package/src/components/menu/index.ts +0 -3
- package/src/components/menu/meta.ts +0 -19
- package/src/components/menu/types.ts +0 -31
- package/src/components/select/Select.tsx +0 -67
- package/src/components/select/index.ts +0 -2
- package/src/components/select/meta.ts +0 -10
- /package/src/{components/app-bar/meta.ts → features/app-bar/appBarMeta.ts} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 15.0.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- 3add861: Adopt `@ankhorage/surface` 5, replace `Menu` and `DropdownMenu` with `PopoverMenu`, make AppBar overflow a real action menu, migrate Breadcrumbs and Select to feature ownership and direct manifest nodes, and present Select with Popover on web and BottomSheetFlatList on native without `@react-native-picker/picker`.
|
|
8
|
+
|
|
9
|
+
## 14.0.1
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- be83fc0: Move AppBar into canonical `src/features/app-bar` ownership while preserving the public root API, and expand the Paradox Usage source with toast, adaptive picker, and direct native BottomSheet examples.
|
|
14
|
+
|
|
3
15
|
## 14.0.0
|
|
4
16
|
|
|
5
17
|
### Major Changes
|
package/README.md
CHANGED
|
@@ -3,17 +3,17 @@
|
|
|
3
3
|
|
|
4
4
|
# @ankhorage/zora
|
|
5
5
|
|
|
6
|
-
         
|
|
7
7
|
|
|
8
8
|
Opinionated React Native and React Native Web UI kit built on @ankhorage/surface.
|
|
9
9
|
|
|
10
10
|
## Usage
|
|
11
11
|
|
|
12
|
-
### ZORA app root with optional runtime capabilities.
|
|
12
|
+
### ZORA app root with optional runtime capabilities and adaptive UI.
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
`useToast()`.
|
|
16
|
-
|
|
14
|
+
Enable only the runtime capabilities the app uses. `toast` installs the host consumed by
|
|
15
|
+
`useToast()`. `bottomSheet` installs the native BottomSheet host; DatePicker and TimePicker use
|
|
16
|
+
that host on native and automatically use Popover on web.
|
|
17
17
|
|
|
18
18
|
Source: `examples/basic-app/App.tsx`
|
|
19
19
|
|
|
@@ -21,12 +21,19 @@ Source: `examples/basic-app/App.tsx`
|
|
|
21
21
|
import {
|
|
22
22
|
AppBar,
|
|
23
23
|
AppShell,
|
|
24
|
+
BottomSheet,
|
|
25
|
+
Button,
|
|
26
|
+
DatePicker,
|
|
24
27
|
Screen,
|
|
25
28
|
ScreenSection,
|
|
29
|
+
Stack,
|
|
26
30
|
Text,
|
|
31
|
+
TimePicker,
|
|
32
|
+
useToast,
|
|
27
33
|
ZoraProvider,
|
|
28
34
|
type ZoraTheme,
|
|
29
35
|
} from '@ankhorage/zora';
|
|
36
|
+
import React from 'react';
|
|
30
37
|
import { GestureHandlerRootView } from 'react-native-gesture-handler';
|
|
31
38
|
|
|
32
39
|
const basicTheme: ZoraTheme = {
|
|
@@ -49,7 +56,7 @@ export default function BasicApp() {
|
|
|
49
56
|
<AppShell header={<AppBar title="Dashboard" subtitle="Welcome to ZORA" />}>
|
|
50
57
|
<Screen>
|
|
51
58
|
<ScreenSection>
|
|
52
|
-
<
|
|
59
|
+
<UsageContent />
|
|
53
60
|
</ScreenSection>
|
|
54
61
|
</Screen>
|
|
55
62
|
</AppShell>
|
|
@@ -57,6 +64,169 @@ export default function BasicApp() {
|
|
|
57
64
|
</GestureHandlerRootView>
|
|
58
65
|
);
|
|
59
66
|
}
|
|
67
|
+
|
|
68
|
+
/*** Demonstrates toast feedback and adaptive picker presentation. */
|
|
69
|
+
function UsageContent() {
|
|
70
|
+
const { showToast } = useToast();
|
|
71
|
+
const [date, setDate] = React.useState<string | null>(null);
|
|
72
|
+
const [time, setTime] = React.useState<string | null>(null);
|
|
73
|
+
|
|
74
|
+
return (
|
|
75
|
+
<Stack gap="m">
|
|
76
|
+
<Text variant="lead">Runtime capabilities are opt-in at the app root.</Text>
|
|
77
|
+
<Button
|
|
78
|
+
onPress={() =>
|
|
79
|
+
showToast({
|
|
80
|
+
description: 'ToastProvider is installed by ZoraProvider.',
|
|
81
|
+
status: 'success',
|
|
82
|
+
title: 'Saved',
|
|
83
|
+
})
|
|
84
|
+
}
|
|
85
|
+
>
|
|
86
|
+
Show toast
|
|
87
|
+
</Button>
|
|
88
|
+
<DatePicker label="Date" onValueChange={setDate} value={date} />
|
|
89
|
+
<TimePicker label="Time" onValueChange={setTime} value={time} />
|
|
90
|
+
</Stack>
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/***
|
|
95
|
+
* Direct native BottomSheet usage.
|
|
96
|
+
*
|
|
97
|
+
* Render this inside `<ZoraProvider bottomSheet>` on native. Web pickers do not need this host;
|
|
98
|
+
* their platform adapters use Popover instead.
|
|
99
|
+
*
|
|
100
|
+
* @usage
|
|
101
|
+
* @readme
|
|
102
|
+
*/
|
|
103
|
+
export function NativeBottomSheetExample() {
|
|
104
|
+
const [open, setOpen] = React.useState(false);
|
|
105
|
+
|
|
106
|
+
return (
|
|
107
|
+
<Stack gap="m">
|
|
108
|
+
<Button onPress={() => setOpen(true)}>Open native bottom sheet</Button>
|
|
109
|
+
<BottomSheet onDismiss={() => setOpen(false)} open={open}>
|
|
110
|
+
<Stack gap="s" p="m">
|
|
111
|
+
<Text variant="label">Bottom sheet content</Text>
|
|
112
|
+
<Button onPress={() => setOpen(false)} variant="ghost">
|
|
113
|
+
Close
|
|
114
|
+
</Button>
|
|
115
|
+
</Stack>
|
|
116
|
+
</BottomSheet>
|
|
117
|
+
</Stack>
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Direct native BottomSheet usage.
|
|
123
|
+
|
|
124
|
+
Render this inside `<ZoraProvider bottomSheet>` on native. Web pickers do not need this host;
|
|
125
|
+
their platform adapters use Popover instead.
|
|
126
|
+
|
|
127
|
+
Source: `examples/basic-app/App.tsx`
|
|
128
|
+
|
|
129
|
+
```tsx
|
|
130
|
+
import {
|
|
131
|
+
AppBar,
|
|
132
|
+
AppShell,
|
|
133
|
+
BottomSheet,
|
|
134
|
+
Button,
|
|
135
|
+
DatePicker,
|
|
136
|
+
Screen,
|
|
137
|
+
ScreenSection,
|
|
138
|
+
Stack,
|
|
139
|
+
Text,
|
|
140
|
+
TimePicker,
|
|
141
|
+
useToast,
|
|
142
|
+
ZoraProvider,
|
|
143
|
+
type ZoraTheme,
|
|
144
|
+
} from '@ankhorage/zora';
|
|
145
|
+
import React from 'react';
|
|
146
|
+
import { GestureHandlerRootView } from 'react-native-gesture-handler';
|
|
147
|
+
|
|
148
|
+
const basicTheme: ZoraTheme = {
|
|
149
|
+
id: 'basic-app',
|
|
150
|
+
name: 'Basic app',
|
|
151
|
+
appCategory: 'developer_tools',
|
|
152
|
+
primaryColor: '#0b6e99',
|
|
153
|
+
harmony: 'analogous',
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
/***
|
|
157
|
+
* ZORA app root with optional runtime capabilities and adaptive UI.
|
|
158
|
+
*
|
|
159
|
+
* Enable only the runtime capabilities the app uses. `toast` installs the host consumed by
|
|
160
|
+
* `useToast()`. `bottomSheet` installs the native BottomSheet host; DatePicker and TimePicker use
|
|
161
|
+
* that host on native and automatically use Popover on web.
|
|
162
|
+
*
|
|
163
|
+
* @usage
|
|
164
|
+
* @readme
|
|
165
|
+
*/
|
|
166
|
+
export default function BasicApp() {
|
|
167
|
+
return (
|
|
168
|
+
<GestureHandlerRootView style={{ flex: 1 }}>
|
|
169
|
+
<ZoraProvider
|
|
170
|
+
bottomSheet
|
|
171
|
+
initialMode="light"
|
|
172
|
+
theme={basicTheme}
|
|
173
|
+
toast={{ defaultDuration: 4000 }}
|
|
174
|
+
>
|
|
175
|
+
<AppShell header={<AppBar title="Dashboard" subtitle="Welcome to ZORA" />}>
|
|
176
|
+
<Screen>
|
|
177
|
+
<ScreenSection>
|
|
178
|
+
<UsageContent />
|
|
179
|
+
</ScreenSection>
|
|
180
|
+
</Screen>
|
|
181
|
+
</AppShell>
|
|
182
|
+
</ZoraProvider>
|
|
183
|
+
</GestureHandlerRootView>
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/*** Demonstrates toast feedback and adaptive picker presentation. */
|
|
188
|
+
function UsageContent() {
|
|
189
|
+
const { showToast } = useToast();
|
|
190
|
+
const [date, setDate] = React.useState<string | null>(null);
|
|
191
|
+
const [time, setTime] = React.useState<string | null>(null);
|
|
192
|
+
|
|
193
|
+
return (
|
|
194
|
+
<Stack gap="m">
|
|
195
|
+
<Text variant="lead">Runtime capabilities are opt-in at the app root.</Text>
|
|
196
|
+
<Button
|
|
197
|
+
onPress={() =>
|
|
198
|
+
showToast({
|
|
199
|
+
description: 'ToastProvider is installed by ZoraProvider.',
|
|
200
|
+
status: 'success',
|
|
201
|
+
title: 'Saved',
|
|
202
|
+
})
|
|
203
|
+
}
|
|
204
|
+
>
|
|
205
|
+
Show toast
|
|
206
|
+
</Button>
|
|
207
|
+
<DatePicker label="Date" onValueChange={setDate} value={date} />
|
|
208
|
+
<TimePicker label="Time" onValueChange={setTime} value={time} />
|
|
209
|
+
</Stack>
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export function NativeBottomSheetExample() {
|
|
214
|
+
const [open, setOpen] = React.useState(false);
|
|
215
|
+
|
|
216
|
+
return (
|
|
217
|
+
<Stack gap="m">
|
|
218
|
+
<Button onPress={() => setOpen(true)}>Open native bottom sheet</Button>
|
|
219
|
+
<BottomSheet onDismiss={() => setOpen(false)} open={open}>
|
|
220
|
+
<Stack gap="s" p="m">
|
|
221
|
+
<Text variant="label">Bottom sheet content</Text>
|
|
222
|
+
<Button onPress={() => setOpen(false)} variant="ghost">
|
|
223
|
+
Close
|
|
224
|
+
</Button>
|
|
225
|
+
</Stack>
|
|
226
|
+
</BottomSheet>
|
|
227
|
+
</Stack>
|
|
228
|
+
);
|
|
229
|
+
}
|
|
60
230
|
```
|
|
61
231
|
|
|
62
232
|
## Generated documentation
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { AppBarProps } from '../../../../types/app-bar';
|
|
3
|
+
/*** Renders a top app bar with title/subtitle and optional leading/trailing actions. */
|
|
4
|
+
export declare const AppBar: (props: AppBarProps) => React.ReactElement | null;
|
|
5
|
+
//# sourceMappingURL=AppBar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AppBar.d.ts","sourceRoot":"","sources":["../../../../../src/features/app-bar/adapters/inbound/AppBar.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAK1B,OAAO,KAAK,EAAkC,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAS7F,wFAAwF;AACxF,eAAO,MAAM,MAAM,mDAAkC,CAAC"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { AppBar as SurfaceAppBar } from '@ankhorage/surface';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { Inline } from '../../../../foundation';
|
|
4
|
+
import { useZoraTheme } from '../../../../theme/useZoraTheme';
|
|
5
|
+
import { withZoraThemeScope } from '../../../../theme/withZoraThemeScope';
|
|
6
|
+
import { IconButton } from '../../../button/public';
|
|
7
|
+
import { Box, Stack } from '../../../layout/public';
|
|
8
|
+
import { PopoverMenu } from '../../../popover-menu/public';
|
|
9
|
+
import { Heading, Text } from '../../../typography/public';
|
|
10
|
+
const DEFAULT_CANCEL_ICON = { name: 'close-outline' };
|
|
11
|
+
const DEFAULT_OVERFLOW_ICON = { name: 'ellipsis-vertical' };
|
|
12
|
+
/*** Renders a top app bar with title/subtitle and optional leading/trailing actions. */
|
|
13
|
+
export const AppBar = withZoraThemeScope(AppBarInner);
|
|
14
|
+
/*** Composes the opinionated ZORA AppBar over the Surface layout primitive. */
|
|
15
|
+
function AppBarInner({ themeId: _themeId, mode: _mode, title, subtitle, leading, actions, overflow, appMode, children, safeAreaTop = true, divider = true, testID, interactionPolicy, }) {
|
|
16
|
+
const { theme } = useZoraTheme();
|
|
17
|
+
const resolvedMode = resolveMode(appMode);
|
|
18
|
+
const isSelectionMode = resolvedMode.type === 'selection';
|
|
19
|
+
const resolvedLeading = leading ?? resolveSelectionLeading(resolvedMode, interactionPolicy);
|
|
20
|
+
const overflowMenu = resolveOverflowMenu(overflow, interactionPolicy, testID);
|
|
21
|
+
const resolvedTrailing = resolveTrailing(actions, overflowMenu);
|
|
22
|
+
const resolvedCenter = resolveCenter({
|
|
23
|
+
children,
|
|
24
|
+
isSelectionMode,
|
|
25
|
+
resolvedMode,
|
|
26
|
+
subtitle,
|
|
27
|
+
title,
|
|
28
|
+
});
|
|
29
|
+
return (<SurfaceAppBar bg={isSelectionMode ? theme.semantics.action.primary.softBg : undefined} divider={divider} leading={resolvedLeading} safeAreaTop={safeAreaTop} testID={testID} trailing={resolvedTrailing}>
|
|
30
|
+
{resolvedCenter ? <Box style={{ minWidth: 0 }}>{resolvedCenter}</Box> : null}
|
|
31
|
+
</SurfaceAppBar>);
|
|
32
|
+
}
|
|
33
|
+
/*** Resolves the effective AppBar mode. */
|
|
34
|
+
function resolveMode(mode) {
|
|
35
|
+
return mode ?? { type: 'default' };
|
|
36
|
+
}
|
|
37
|
+
/*** Formats the active selection label with its optional count. */
|
|
38
|
+
function resolveSelectionLabel({ count, label }) {
|
|
39
|
+
if (count === undefined)
|
|
40
|
+
return label;
|
|
41
|
+
return `${label} (${count})`;
|
|
42
|
+
}
|
|
43
|
+
/*** Resolves the accessible label for the overflow menu trigger. */
|
|
44
|
+
function resolveOverflowLabel(overflow) {
|
|
45
|
+
return overflow.label ?? 'More options';
|
|
46
|
+
}
|
|
47
|
+
/*** Resolves the accessible label for leaving selection mode. */
|
|
48
|
+
function resolveCancelLabel(mode) {
|
|
49
|
+
return mode.cancelLabel ?? 'Cancel selection';
|
|
50
|
+
}
|
|
51
|
+
/*** Resolves the selection action shown at the leading edge. */
|
|
52
|
+
function resolveSelectionLeading(mode, interactionPolicy) {
|
|
53
|
+
if (mode.type !== 'selection')
|
|
54
|
+
return undefined;
|
|
55
|
+
return (<IconButton color="neutral" icon={mode.cancelIcon ?? DEFAULT_CANCEL_ICON} interactionPolicy={interactionPolicy} label={resolveCancelLabel(mode)} onPress={mode.onCancel} size="m" variant="ghost"/>);
|
|
56
|
+
}
|
|
57
|
+
/*** Resolves the optional AppBar overflow action menu. */
|
|
58
|
+
function resolveOverflowMenu(overflow, interactionPolicy, testID) {
|
|
59
|
+
if (overflow === undefined || overflow.actions.length === 0)
|
|
60
|
+
return null;
|
|
61
|
+
return (<PopoverMenu actions={overflow.actions} closeOnSelect={overflow.closeOnSelect} interactionPolicy={interactionPolicy} onDismiss={overflow.onDismiss} testID={testID ? `${testID}-overflow` : undefined} trigger={({ toggle }) => (<IconButton color="neutral" disabled={overflow.disabled} icon={overflow.icon ?? DEFAULT_OVERFLOW_ICON} interactionPolicy={interactionPolicy} label={resolveOverflowLabel(overflow)} onPress={toggle} size="m" variant="ghost"/>)}/>);
|
|
62
|
+
}
|
|
63
|
+
/*** Composes trailing actions and overflow controls. */
|
|
64
|
+
function resolveTrailing(actions, overflowMenu) {
|
|
65
|
+
if (!actions && !overflowMenu)
|
|
66
|
+
return undefined;
|
|
67
|
+
return (<Inline align="center" gap="s" wrap="nowrap">
|
|
68
|
+
{actions}
|
|
69
|
+
{overflowMenu}
|
|
70
|
+
</Inline>);
|
|
71
|
+
}
|
|
72
|
+
/*** Resolves the center content for default and selection modes. */
|
|
73
|
+
function resolveCenter({ children, isSelectionMode, resolvedMode, subtitle, title, }) {
|
|
74
|
+
if (children !== undefined)
|
|
75
|
+
return children;
|
|
76
|
+
if (isSelectionMode && resolvedMode.type === 'selection') {
|
|
77
|
+
return (<Text emphasis="default" numberOfLines={1} variant="label" weight="semiBold">
|
|
78
|
+
{resolveSelectionLabel(resolvedMode)}
|
|
79
|
+
</Text>);
|
|
80
|
+
}
|
|
81
|
+
if (title == null && subtitle == null)
|
|
82
|
+
return null;
|
|
83
|
+
return (<Stack gap="xs">
|
|
84
|
+
{title != null ? (<Heading ellipsizeMode="tail" level={3} numberOfLines={1} size="h5">
|
|
85
|
+
{title}
|
|
86
|
+
</Heading>) : null}
|
|
87
|
+
{subtitle != null ? (<Text ellipsizeMode="tail" emphasis="muted" numberOfLines={1} variant="bodySmall">
|
|
88
|
+
{subtitle}
|
|
89
|
+
</Text>) : null}
|
|
90
|
+
</Stack>);
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=AppBar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AppBar.js","sourceRoot":"","sources":["../../../../../src/features/app-bar/adapters/inbound/AppBar.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,aAAa,EAAuB,MAAM,oBAAoB,CAAC;AAClF,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,sCAAsC,CAAC;AAE1E,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAC3D,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,4BAA4B,CAAC;AAE3D,MAAM,mBAAmB,GAAG,EAAE,IAAI,EAAE,eAAe,EAA2B,CAAC;AAC/E,MAAM,qBAAqB,GAAG,EAAE,IAAI,EAAE,mBAAmB,EAA2B,CAAC;AAErF,wFAAwF;AACxF,MAAM,CAAC,MAAM,MAAM,GAAG,kBAAkB,CAAC,WAAW,CAAC,CAAC;AAEtD,+EAA+E;AAC/E,SAAS,WAAW,CAAC,EACnB,OAAO,EAAE,QAAQ,EACjB,IAAI,EAAE,KAAK,EACX,KAAK,EACL,QAAQ,EACR,OAAO,EACP,OAAO,EACP,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,WAAW,GAAG,IAAI,EAClB,OAAO,GAAG,IAAI,EACd,MAAM,EACN,iBAAiB,GACL;IACZ,MAAM,EAAE,KAAK,EAAE,GAAG,YAAY,EAAE,CAAC;IACjC,MAAM,YAAY,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IAC1C,MAAM,eAAe,GAAG,YAAY,CAAC,IAAI,KAAK,WAAW,CAAC;IAC1D,MAAM,eAAe,GAAG,OAAO,IAAI,uBAAuB,CAAC,YAAY,EAAE,iBAAiB,CAAC,CAAC;IAC5F,MAAM,YAAY,GAAG,mBAAmB,CAAC,QAAQ,EAAE,iBAAiB,EAAE,MAAM,CAAC,CAAC;IAC9E,MAAM,gBAAgB,GAAG,eAAe,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;IAChE,MAAM,cAAc,GAAG,aAAa,CAAC;QACnC,QAAQ;QACR,eAAe;QACf,YAAY;QACZ,QAAQ;QACR,KAAK;KACN,CAAC,CAAC;IAEH,OAAO,CACL,CAAC,aAAa,CACZ,EAAE,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CACxE,OAAO,CAAC,CAAC,OAAO,CAAC,CACjB,OAAO,CAAC,CAAC,eAAe,CAAC,CACzB,WAAW,CAAC,CAAC,WAAW,CAAC,CACzB,MAAM,CAAC,CAAC,MAAM,CAAC,CACf,QAAQ,CAAC,CAAC,gBAAgB,CAAC,CAE3B;MAAA,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,cAAc,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAC9E;IAAA,EAAE,aAAa,CAAC,CACjB,CAAC;AACJ,CAAC;AAED,2CAA2C;AAC3C,SAAS,WAAW,CAAC,IAA4B;IAC/C,OAAO,IAAI,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;AACrC,CAAC;AAED,mEAAmE;AACnE,SAAS,qBAAqB,CAAC,EAAE,KAAK,EAAE,KAAK,EAAqC;IAChF,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACtC,OAAO,GAAG,KAAK,KAAK,KAAK,GAAG,CAAC;AAC/B,CAAC;AAED,oEAAoE;AACpE,SAAS,oBAAoB,CAAC,QAA4B;IACxD,OAAO,QAAQ,CAAC,KAAK,IAAI,cAAc,CAAC;AAC1C,CAAC;AAED,iEAAiE;AACjE,SAAS,kBAAkB,CAAC,IAAgD;IAC1E,OAAO,IAAI,CAAC,WAAW,IAAI,kBAAkB,CAAC;AAChD,CAAC;AAED,gEAAgE;AAChE,SAAS,uBAAuB,CAC9B,IAAgB,EAChB,iBAAmD;IAEnD,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW;QAAE,OAAO,SAAS,CAAC;IAEhD,OAAO,CACL,CAAC,UAAU,CACT,KAAK,CAAC,SAAS,CACf,IAAI,CAAC,CAAC,IAAI,CAAC,UAAU,IAAI,mBAAmB,CAAC,CAC7C,iBAAiB,CAAC,CAAC,iBAAiB,CAAC,CACrC,KAAK,CAAC,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAChC,OAAO,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CACvB,IAAI,CAAC,GAAG,CACR,OAAO,CAAC,OAAO,EACf,CACH,CAAC;AACJ,CAAC;AAED,0DAA0D;AAC1D,SAAS,mBAAmB,CAC1B,QAAwC,EACxC,iBAAmD,EACnD,MAA0B;IAE1B,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAEzE,OAAO,CACL,CAAC,WAAW,CACV,OAAO,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAC1B,aAAa,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,CACtC,iBAAiB,CAAC,CAAC,iBAAiB,CAAC,CACrC,SAAS,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,CAC9B,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAClD,OAAO,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CACvB,CAAC,UAAU,CACT,KAAK,CAAC,SAAS,CACf,QAAQ,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAC5B,IAAI,CAAC,CAAC,QAAQ,CAAC,IAAI,IAAI,qBAAqB,CAAC,CAC7C,iBAAiB,CAAC,CAAC,iBAAiB,CAAC,CACrC,KAAK,CAAC,CAAC,oBAAoB,CAAC,QAAQ,CAAC,CAAC,CACtC,OAAO,CAAC,CAAC,MAAM,CAAC,CAChB,IAAI,CAAC,GAAG,CACR,OAAO,CAAC,OAAO,EACf,CACH,CAAC,EACF,CACH,CAAC;AACJ,CAAC;AAED,wDAAwD;AACxD,SAAS,eAAe,CAAC,OAAwB,EAAE,YAA6B;IAC9E,IAAI,CAAC,OAAO,IAAI,CAAC,YAAY;QAAE,OAAO,SAAS,CAAC;IAChD,OAAO,CACL,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAC1C;MAAA,CAAC,OAAO,CACR;MAAA,CAAC,YAAY,CACf;IAAA,EAAE,MAAM,CAAC,CACV,CAAC;AACJ,CAAC;AAED,oEAAoE;AACpE,SAAS,aAAa,CAAC,EACrB,QAAQ,EACR,eAAe,EACf,YAAY,EACZ,QAAQ,EACR,KAAK,GAON;IACC,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC;IAC5C,IAAI,eAAe,IAAI,YAAY,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;QACzD,OAAO,CACL,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,CAC1E;QAAA,CAAC,qBAAqB,CAAC,YAAY,CAAC,CACtC;MAAA,EAAE,IAAI,CAAC,CACR,CAAC;IACJ,CAAC;IACD,IAAI,KAAK,IAAI,IAAI,IAAI,QAAQ,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC;IAEnD,OAAO,CACL,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CACb;MAAA,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,CACf,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CACjE;UAAA,CAAC,KAAK,CACR;QAAA,EAAE,OAAO,CAAC,CACX,CAAC,CAAC,CAAC,IAAI,CACR;MAAA,CAAC,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,CAClB,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,CAC/E;UAAA,CAAC,QAAQ,CACX;QAAA,EAAE,IAAI,CAAC,CACR,CAAC,CAAC,CAAC,IAAI,CACV;IAAA,EAAE,KAAK,CAAC,CACT,CAAC;AACJ,CAAC","sourcesContent":["import { AppBar as SurfaceAppBar, type ButtonIconSpec } from '@ankhorage/surface';\nimport React from 'react';\n\nimport { Inline } from '../../../../foundation';\nimport { useZoraTheme } from '../../../../theme/useZoraTheme';\nimport { withZoraThemeScope } from '../../../../theme/withZoraThemeScope';\nimport type { AppBarMode, AppBarOverflowMenu, AppBarProps } from '../../../../types/app-bar';\nimport { IconButton } from '../../../button/public';\nimport { Box, Stack } from '../../../layout/public';\nimport { PopoverMenu } from '../../../popover-menu/public';\nimport { Heading, Text } from '../../../typography/public';\n\nconst DEFAULT_CANCEL_ICON = { name: 'close-outline' } satisfies ButtonIconSpec;\nconst DEFAULT_OVERFLOW_ICON = { name: 'ellipsis-vertical' } satisfies ButtonIconSpec;\n\n/*** Renders a top app bar with title/subtitle and optional leading/trailing actions. */\nexport const AppBar = withZoraThemeScope(AppBarInner);\n\n/*** Composes the opinionated ZORA AppBar over the Surface layout primitive. */\nfunction AppBarInner({\n themeId: _themeId,\n mode: _mode,\n title,\n subtitle,\n leading,\n actions,\n overflow,\n appMode,\n children,\n safeAreaTop = true,\n divider = true,\n testID,\n interactionPolicy,\n}: AppBarProps) {\n const { theme } = useZoraTheme();\n const resolvedMode = resolveMode(appMode);\n const isSelectionMode = resolvedMode.type === 'selection';\n const resolvedLeading = leading ?? resolveSelectionLeading(resolvedMode, interactionPolicy);\n const overflowMenu = resolveOverflowMenu(overflow, interactionPolicy, testID);\n const resolvedTrailing = resolveTrailing(actions, overflowMenu);\n const resolvedCenter = resolveCenter({\n children,\n isSelectionMode,\n resolvedMode,\n subtitle,\n title,\n });\n\n return (\n <SurfaceAppBar\n bg={isSelectionMode ? theme.semantics.action.primary.softBg : undefined}\n divider={divider}\n leading={resolvedLeading}\n safeAreaTop={safeAreaTop}\n testID={testID}\n trailing={resolvedTrailing}\n >\n {resolvedCenter ? <Box style={{ minWidth: 0 }}>{resolvedCenter}</Box> : null}\n </SurfaceAppBar>\n );\n}\n\n/*** Resolves the effective AppBar mode. */\nfunction resolveMode(mode: AppBarMode | undefined): AppBarMode {\n return mode ?? { type: 'default' };\n}\n\n/*** Formats the active selection label with its optional count. */\nfunction resolveSelectionLabel({ count, label }: { count?: number; label: string }): string {\n if (count === undefined) return label;\n return `${label} (${count})`;\n}\n\n/*** Resolves the accessible label for the overflow menu trigger. */\nfunction resolveOverflowLabel(overflow: AppBarOverflowMenu): string {\n return overflow.label ?? 'More options';\n}\n\n/*** Resolves the accessible label for leaving selection mode. */\nfunction resolveCancelLabel(mode: Extract<AppBarMode, { type: 'selection' }>): string {\n return mode.cancelLabel ?? 'Cancel selection';\n}\n\n/*** Resolves the selection action shown at the leading edge. */\nfunction resolveSelectionLeading(\n mode: AppBarMode,\n interactionPolicy: AppBarProps['interactionPolicy'],\n): React.ReactNode | undefined {\n if (mode.type !== 'selection') return undefined;\n\n return (\n <IconButton\n color=\"neutral\"\n icon={mode.cancelIcon ?? DEFAULT_CANCEL_ICON}\n interactionPolicy={interactionPolicy}\n label={resolveCancelLabel(mode)}\n onPress={mode.onCancel}\n size=\"m\"\n variant=\"ghost\"\n />\n );\n}\n\n/*** Resolves the optional AppBar overflow action menu. */\nfunction resolveOverflowMenu(\n overflow: AppBarOverflowMenu | undefined,\n interactionPolicy: AppBarProps['interactionPolicy'],\n testID: string | undefined,\n): React.ReactNode {\n if (overflow === undefined || overflow.actions.length === 0) return null;\n\n return (\n <PopoverMenu\n actions={overflow.actions}\n closeOnSelect={overflow.closeOnSelect}\n interactionPolicy={interactionPolicy}\n onDismiss={overflow.onDismiss}\n testID={testID ? `${testID}-overflow` : undefined}\n trigger={({ toggle }) => (\n <IconButton\n color=\"neutral\"\n disabled={overflow.disabled}\n icon={overflow.icon ?? DEFAULT_OVERFLOW_ICON}\n interactionPolicy={interactionPolicy}\n label={resolveOverflowLabel(overflow)}\n onPress={toggle}\n size=\"m\"\n variant=\"ghost\"\n />\n )}\n />\n );\n}\n\n/*** Composes trailing actions and overflow controls. */\nfunction resolveTrailing(actions: React.ReactNode, overflowMenu: React.ReactNode): React.ReactNode {\n if (!actions && !overflowMenu) return undefined;\n return (\n <Inline align=\"center\" gap=\"s\" wrap=\"nowrap\">\n {actions}\n {overflowMenu}\n </Inline>\n );\n}\n\n/*** Resolves the center content for default and selection modes. */\nfunction resolveCenter({\n children,\n isSelectionMode,\n resolvedMode,\n subtitle,\n title,\n}: {\n children: React.ReactNode;\n isSelectionMode: boolean;\n resolvedMode: AppBarMode;\n subtitle: React.ReactNode;\n title: React.ReactNode;\n}): React.ReactNode {\n if (children !== undefined) return children;\n if (isSelectionMode && resolvedMode.type === 'selection') {\n return (\n <Text emphasis=\"default\" numberOfLines={1} variant=\"label\" weight=\"semiBold\">\n {resolveSelectionLabel(resolvedMode)}\n </Text>\n );\n }\n if (title == null && subtitle == null) return null;\n\n return (\n <Stack gap=\"xs\">\n {title != null ? (\n <Heading ellipsizeMode=\"tail\" level={3} numberOfLines={1} size=\"h5\">\n {title}\n </Heading>\n ) : null}\n {subtitle != null ? (\n <Text ellipsizeMode=\"tail\" emphasis=\"muted\" numberOfLines={1} variant=\"bodySmall\">\n {subtitle}\n </Text>\n ) : null}\n </Stack>\n );\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"appBarMeta.d.ts","sourceRoot":"","sources":["../../../src/features/app-bar/appBarMeta.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,UAAU;;;;;;;CAOe,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"appBarMeta.js","sourceRoot":"","sources":["../../../src/features/app-bar/appBarMeta.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,IAAI,EAAE,QAAQ;IACd,QAAQ,EAAE,WAAW;IACrB,kBAAkB,EAAE,KAAK;IACzB,eAAe,EAAE,EAAE;IACnB,IAAI,EAAE,yEAAyE;IAC/E,KAAK,EAAE,EAAE;CAC2B,CAAC","sourcesContent":["import type { ZoraComponentMeta } from '../../metadata';\n\nexport const appBarMeta = {\n name: 'AppBar',\n category: 'component',\n directManifestNode: false,\n allowedChildren: [],\n note: 'Application chrome component; not represented as a manifest node in v1.',\n props: {},\n} as const satisfies ZoraComponentMeta;\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../../src/features/app-bar/public.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,UAAU,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvF,OAAO,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"public.js","sourceRoot":"","sources":["../../../src/features/app-bar/public.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAC","sourcesContent":["export type { AppBarMode, AppBarOverflowMenu, AppBarProps } from '../../types/app-bar';\nexport { AppBar } from './adapters/inbound/AppBar';\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export type { BottomSheetProps } from '../../types/manifest-bottom-sheet';
|
|
2
2
|
export { BottomSheet } from './adapters/inbound/BottomSheet';
|
|
3
|
-
export type { BottomSheetController, BottomSheetPresentOptions, } from '@ankhorage/surface/bottom-sheet';
|
|
4
|
-
export { useBottomSheet } from '@ankhorage/surface/bottom-sheet';
|
|
3
|
+
export type { BottomSheetContentMode, BottomSheetController, BottomSheetPresentOptions, } from '@ankhorage/surface/bottom-sheet';
|
|
4
|
+
export { BottomSheetFlatList, BottomSheetScrollView, BottomSheetSectionList, BottomSheetView, BottomSheetVirtualizedList, useBottomSheet, } from '@ankhorage/surface/bottom-sheet';
|
|
5
5
|
//# sourceMappingURL=public.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../../src/features/bottom-sheet/public.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAC1E,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAC7D,YAAY,EACV,qBAAqB,EACrB,yBAAyB,GAC1B,MAAM,iCAAiC,CAAC;AACzC,OAAO,
|
|
1
|
+
{"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../../src/features/bottom-sheet/public.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAC1E,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAC7D,YAAY,EACV,sBAAsB,EACtB,qBAAqB,EACrB,yBAAyB,GAC1B,MAAM,iCAAiC,CAAC;AACzC,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,sBAAsB,EACtB,eAAe,EACf,0BAA0B,EAC1B,cAAc,GACf,MAAM,iCAAiC,CAAC"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { BottomSheet } from './adapters/inbound/BottomSheet';
|
|
2
|
-
export { useBottomSheet } from '@ankhorage/surface/bottom-sheet';
|
|
2
|
+
export { BottomSheetFlatList, BottomSheetScrollView, BottomSheetSectionList, BottomSheetView, BottomSheetVirtualizedList, useBottomSheet, } from '@ankhorage/surface/bottom-sheet';
|
|
3
3
|
//# sourceMappingURL=public.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public.js","sourceRoot":"","sources":["../../../src/features/bottom-sheet/public.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"public.js","sourceRoot":"","sources":["../../../src/features/bottom-sheet/public.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAM7D,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,sBAAsB,EACtB,eAAe,EACf,0BAA0B,EAC1B,cAAc,GACf,MAAM,iCAAiC,CAAC","sourcesContent":["export type { BottomSheetProps } from '../../types/manifest-bottom-sheet';\nexport { BottomSheet } from './adapters/inbound/BottomSheet';\nexport type {\n BottomSheetContentMode,\n BottomSheetController,\n BottomSheetPresentOptions,\n} from '@ankhorage/surface/bottom-sheet';\nexport {\n BottomSheetFlatList,\n BottomSheetScrollView,\n BottomSheetSectionList,\n BottomSheetView,\n BottomSheetVirtualizedList,\n useBottomSheet,\n} from '@ankhorage/surface/bottom-sheet';\n"]}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { BreadcrumbsProps } from '../../../../types/breadcrumbs';
|
|
3
|
+
/*** Renders a breadcrumb trail whose final item represents the current location. */
|
|
4
|
+
export declare const Breadcrumbs: (props: BreadcrumbsProps) => React.ReactElement | null;
|
|
5
|
+
//# sourceMappingURL=Breadcrumbs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Breadcrumbs.d.ts","sourceRoot":"","sources":["../../../../../src/features/breadcrumbs/adapters/inbound/Breadcrumbs.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAM1B,OAAO,KAAK,EAGV,gBAAgB,EACjB,MAAM,+BAA+B,CAAC;AAKvC,oFAAoF;AACpF,eAAO,MAAM,WAAW,wDAAuC,CAAC"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Inline } from '../../../../foundation';
|
|
3
|
+
import { resolveIconSize } from '../../../../internal/recipes';
|
|
4
|
+
import { useZoraTheme } from '../../../../theme/useZoraTheme';
|
|
5
|
+
import { withZoraThemeScope } from '../../../../theme/withZoraThemeScope';
|
|
6
|
+
import { Button } from '../../../button/public';
|
|
7
|
+
import { Icon } from '../../../icon/public';
|
|
8
|
+
import { Text } from '../../../typography/public';
|
|
9
|
+
/*** Renders a breadcrumb trail whose final item represents the current location. */
|
|
10
|
+
export const Breadcrumbs = withZoraThemeScope(BreadcrumbsInner);
|
|
11
|
+
/*** Connects serializable breadcrumb items to the component-level item press event. */
|
|
12
|
+
function BreadcrumbsInner({ themeId: _themeId, mode: _mode, interactionPolicy, items, separator = '/', maxItems, compact = false, disabled = false, onItemPress, testID, }) {
|
|
13
|
+
const normalizedMaxItems = normalizeMaxItems(maxItems);
|
|
14
|
+
const renderItems = createRenderItems(items, normalizedMaxItems);
|
|
15
|
+
const currentItemId = items.at(-1)?.id;
|
|
16
|
+
if (items.length === 0)
|
|
17
|
+
return null;
|
|
18
|
+
return (<Inline align="center" gap={compact ? 'xs' : 's'} testID={testID} wrap="wrap">
|
|
19
|
+
{renderItems.map((renderItem, index) => {
|
|
20
|
+
const showSeparator = index !== renderItems.length - 1;
|
|
21
|
+
if (renderItem.type === 'ellipsis') {
|
|
22
|
+
return (<React.Fragment key="ellipsis">
|
|
23
|
+
<Text emphasis="muted" variant={compact ? 'caption' : 'bodySmall'}>
|
|
24
|
+
…
|
|
25
|
+
</Text>
|
|
26
|
+
{showSeparator ? renderSeparator(separator) : null}
|
|
27
|
+
</React.Fragment>);
|
|
28
|
+
}
|
|
29
|
+
return (<BreadcrumbItemView compact={compact} current={renderItem.item.id === currentItemId} disabled={disabled} interactionPolicy={interactionPolicy} item={renderItem.item} key={renderItem.item.id} onItemPress={onItemPress} separator={showSeparator ? separator : undefined} testID={testID}/>);
|
|
30
|
+
})}
|
|
31
|
+
</Inline>);
|
|
32
|
+
}
|
|
33
|
+
/*** Renders one breadcrumb item and its optional following separator. */
|
|
34
|
+
function BreadcrumbItemView({ compact, current, disabled, interactionPolicy, item, onItemPress, separator, testID, }) {
|
|
35
|
+
const interactive = !current && !disabled && !item.disabled && onItemPress !== undefined;
|
|
36
|
+
return (<>
|
|
37
|
+
{interactive ? (<Button color="neutral" interactionPolicy={interactionPolicy} leadingIcon={item.icon} onPress={() => onItemPress({ id: item.id })} size={compact ? 's' : 'm'} testID={testID ? `${testID}-item-${item.id}` : undefined} variant="ghost">
|
|
38
|
+
{item.label}
|
|
39
|
+
</Button>) : (<BreadcrumbLabel compact={compact} item={item}/>)}
|
|
40
|
+
{separator === undefined ? null : renderSeparator(separator)}
|
|
41
|
+
</>);
|
|
42
|
+
}
|
|
43
|
+
/*** Renders one non-interactive breadcrumb label. */
|
|
44
|
+
function BreadcrumbLabel({ item, compact }) {
|
|
45
|
+
const { theme } = useZoraTheme();
|
|
46
|
+
return (<Inline align="center" gap="xs" wrap="nowrap">
|
|
47
|
+
{item.icon ? (<Icon {...item.icon} color={theme.semantics.content.muted} size={resolveIconSize(compact ? 's' : 'm')}/>) : null}
|
|
48
|
+
<Text emphasis="muted" variant={compact ? 'caption' : 'bodySmall'}>
|
|
49
|
+
{item.label}
|
|
50
|
+
</Text>
|
|
51
|
+
</Inline>);
|
|
52
|
+
}
|
|
53
|
+
/*** Renders the configured separator with muted breadcrumb styling. */
|
|
54
|
+
function renderSeparator(separator) {
|
|
55
|
+
return (<Text emphasis="muted" variant="bodySmall">
|
|
56
|
+
{separator}
|
|
57
|
+
</Text>);
|
|
58
|
+
}
|
|
59
|
+
/*** Normalizes an optional maximum breadcrumb item count. */
|
|
60
|
+
function normalizeMaxItems(value) {
|
|
61
|
+
if (value === undefined || !Number.isFinite(value))
|
|
62
|
+
return undefined;
|
|
63
|
+
return Math.max(0, Math.trunc(value));
|
|
64
|
+
}
|
|
65
|
+
/*** Collapses middle breadcrumb items into one ellipsis when required. */
|
|
66
|
+
function createRenderItems(items, maxItems) {
|
|
67
|
+
if (maxItems === undefined || maxItems === 0 || items.length <= maxItems || maxItems < 3) {
|
|
68
|
+
return items.map((item) => ({ item, type: 'item' }));
|
|
69
|
+
}
|
|
70
|
+
const firstItem = items.at(0);
|
|
71
|
+
if (firstItem === undefined)
|
|
72
|
+
return [];
|
|
73
|
+
const trailingCount = maxItems - 2;
|
|
74
|
+
const trailingItems = items.slice(items.length - trailingCount);
|
|
75
|
+
return [
|
|
76
|
+
{ item: firstItem, type: 'item' },
|
|
77
|
+
{ type: 'ellipsis' },
|
|
78
|
+
...trailingItems.map((item) => ({ item, type: 'item' })),
|
|
79
|
+
];
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=Breadcrumbs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Breadcrumbs.js","sourceRoot":"","sources":["../../../../../src/features/breadcrumbs/adapters/inbound/Breadcrumbs.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from 'react';\n\nimport { Inline } from '../../../../foundation';\nimport { resolveIconSize } from '../../../../internal/recipes';\nimport { useZoraTheme } from '../../../../theme/useZoraTheme';\nimport { withZoraThemeScope } from '../../../../theme/withZoraThemeScope';\nimport type {\n BreadcrumbItem,\n BreadcrumbPressEvent,\n BreadcrumbsProps,\n} from '../../../../types/breadcrumbs';\nimport { Button } from '../../../button/public';\nimport { Icon } from '../../../icon/public';\nimport { Text } from '../../../typography/public';\n\n/*** Renders a breadcrumb trail whose final item represents the current location. */\nexport const Breadcrumbs = withZoraThemeScope(BreadcrumbsInner);\n\ntype BreadcrumbRenderItem =\n | {\n item: BreadcrumbItem;\n type: 'item';\n }\n | {\n type: 'ellipsis';\n };\n\n/*** Connects serializable breadcrumb items to the component-level item press event. */\nfunction BreadcrumbsInner({\n themeId: _themeId,\n mode: _mode,\n interactionPolicy,\n items,\n separator = '/',\n maxItems,\n compact = false,\n disabled = false,\n onItemPress,\n testID,\n}: BreadcrumbsProps) {\n const normalizedMaxItems = normalizeMaxItems(maxItems);\n const renderItems = createRenderItems(items, normalizedMaxItems);\n const currentItemId = items.at(-1)?.id;\n\n if (items.length === 0) return null;\n\n return (\n <Inline align=\"center\" gap={compact ? 'xs' : 's'} testID={testID} wrap=\"wrap\">\n {renderItems.map((renderItem, index) => {\n const showSeparator = index !== renderItems.length - 1;\n\n if (renderItem.type === 'ellipsis') {\n return (\n <React.Fragment key=\"ellipsis\">\n <Text emphasis=\"muted\" variant={compact ? 'caption' : 'bodySmall'}>\n …\n </Text>\n {showSeparator ? renderSeparator(separator) : null}\n </React.Fragment>\n );\n }\n\n return (\n <BreadcrumbItemView\n compact={compact}\n current={renderItem.item.id === currentItemId}\n disabled={disabled}\n interactionPolicy={interactionPolicy}\n item={renderItem.item}\n key={renderItem.item.id}\n onItemPress={onItemPress}\n separator={showSeparator ? separator : undefined}\n testID={testID}\n />\n );\n })}\n </Inline>\n );\n}\n\n/*** Renders one breadcrumb item and its optional following separator. */\nfunction BreadcrumbItemView({\n compact,\n current,\n disabled,\n interactionPolicy,\n item,\n onItemPress,\n separator,\n testID,\n}: {\n compact: boolean;\n current: boolean;\n disabled: boolean;\n interactionPolicy: BreadcrumbsProps['interactionPolicy'];\n item: BreadcrumbItem;\n onItemPress: ((event: BreadcrumbPressEvent) => void) | undefined;\n separator: string | undefined;\n testID: string | undefined;\n}) {\n const interactive = !current && !disabled && !item.disabled && onItemPress !== undefined;\n\n return (\n <>\n {interactive ? (\n <Button\n color=\"neutral\"\n interactionPolicy={interactionPolicy}\n leadingIcon={item.icon}\n onPress={() => onItemPress({ id: item.id })}\n size={compact ? 's' : 'm'}\n testID={testID ? `${testID}-item-${item.id}` : undefined}\n variant=\"ghost\"\n >\n {item.label}\n </Button>\n ) : (\n <BreadcrumbLabel compact={compact} item={item} />\n )}\n {separator === undefined ? null : renderSeparator(separator)}\n </>\n );\n}\n\n/*** Renders one non-interactive breadcrumb label. */\nfunction BreadcrumbLabel({ item, compact }: { item: BreadcrumbItem; compact: boolean }) {\n const { theme } = useZoraTheme();\n\n return (\n <Inline align=\"center\" gap=\"xs\" wrap=\"nowrap\">\n {item.icon ? (\n <Icon\n {...item.icon}\n color={theme.semantics.content.muted}\n size={resolveIconSize(compact ? 's' : 'm')}\n />\n ) : null}\n <Text emphasis=\"muted\" variant={compact ? 'caption' : 'bodySmall'}>\n {item.label}\n </Text>\n </Inline>\n );\n}\n\n/*** Renders the configured separator with muted breadcrumb styling. */\nfunction renderSeparator(separator: string): React.ReactNode {\n return (\n <Text emphasis=\"muted\" variant=\"bodySmall\">\n {separator}\n </Text>\n );\n}\n\n/*** Normalizes an optional maximum breadcrumb item count. */\nfunction normalizeMaxItems(value: number | undefined): number | undefined {\n if (value === undefined || !Number.isFinite(value)) return undefined;\n return Math.max(0, Math.trunc(value));\n}\n\n/*** Collapses middle breadcrumb items into one ellipsis when required. */\nfunction createRenderItems(\n items: readonly BreadcrumbItem[],\n maxItems: number | undefined,\n): readonly BreadcrumbRenderItem[] {\n if (maxItems === undefined || maxItems === 0 || items.length <= maxItems || maxItems < 3) {\n return items.map((item) => ({ item, type: 'item' }));\n }\n\n const firstItem = items.at(0);\n if (firstItem === undefined) return [];\n\n const trailingCount = maxItems - 2;\n const trailingItems = items.slice(items.length - trailingCount);\n return [\n { item: firstItem, type: 'item' },\n { type: 'ellipsis' },\n ...trailingItems.map((item) => ({ item, type: 'item' }) satisfies BreadcrumbRenderItem),\n ];\n}\n"]}
|