@ankhorage/zora 2.5.0 → 2.5.2
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 +593 -1
- package/dist/components/button/Button.d.ts +12 -0
- package/dist/components/button/Button.d.ts.map +1 -1
- package/dist/components/button/Button.js +12 -0
- package/dist/components/button/Button.js.map +1 -1
- package/dist/components/card/Card.d.ts +12 -0
- package/dist/components/card/Card.d.ts.map +1 -1
- package/dist/components/card/Card.js +12 -0
- package/dist/components/card/Card.js.map +1 -1
- package/dist/components/heading/Heading.d.ts +12 -0
- package/dist/components/heading/Heading.d.ts.map +1 -1
- package/dist/components/heading/Heading.js +12 -0
- package/dist/components/heading/Heading.js.map +1 -1
- package/dist/components/input/Input.d.ts +12 -0
- package/dist/components/input/Input.d.ts.map +1 -1
- package/dist/components/input/Input.js +12 -0
- package/dist/components/input/Input.js.map +1 -1
- package/dist/components/text/Text.d.ts +12 -0
- package/dist/components/text/Text.d.ts.map +1 -1
- package/dist/components/text/Text.js +12 -0
- package/dist/components/text/Text.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/layout/app-shell/AppShell.d.ts +12 -0
- package/dist/layout/app-shell/AppShell.d.ts.map +1 -1
- package/dist/layout/app-shell/AppShell.js +12 -0
- package/dist/layout/app-shell/AppShell.js.map +1 -1
- package/dist/patterns/empty-state/EmptyState.d.ts +12 -0
- package/dist/patterns/empty-state/EmptyState.d.ts.map +1 -1
- package/dist/patterns/empty-state/EmptyState.js +12 -0
- package/dist/patterns/empty-state/EmptyState.js.map +1 -1
- package/dist/patterns/responsive-panel/ResponsivePanel.d.ts +12 -0
- package/dist/patterns/responsive-panel/ResponsivePanel.d.ts.map +1 -1
- package/dist/patterns/responsive-panel/ResponsivePanel.js +72 -7
- package/dist/patterns/responsive-panel/ResponsivePanel.js.map +1 -1
- package/dist/patterns/responsive-panel/types.d.ts +4 -0
- package/dist/patterns/responsive-panel/types.d.ts.map +1 -1
- package/dist/patterns/responsive-panel/types.js.map +1 -1
- package/dist/theme/ZoraProvider.d.ts +12 -0
- package/dist/theme/ZoraProvider.d.ts.map +1 -1
- package/dist/theme/ZoraProvider.js +12 -0
- package/dist/theme/ZoraProvider.js.map +1 -1
- package/package.json +1 -1
- package/src/components/button/Button.tsx +12 -0
- package/src/components/card/Card.tsx +12 -0
- package/src/components/heading/Heading.tsx +12 -0
- package/src/components/input/Input.tsx +12 -0
- package/src/components/text/Text.tsx +12 -0
- package/src/index.ts +2 -0
- package/src/layout/app-shell/AppShell.tsx +12 -0
- package/src/patterns/empty-state/EmptyState.tsx +12 -0
- package/src/patterns/responsive-panel/ResponsivePanel.tsx +90 -6
- package/src/patterns/responsive-panel/types.ts +4 -0
- package/src/theme/ZoraProvider.tsx +12 -0
|
@@ -1,4 +1,16 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { ResponsivePanelProps } from './types';
|
|
3
|
+
/***
|
|
4
|
+
* Adaptive secondary surface that can render as an inline panel, drawer, or modal.
|
|
5
|
+
*
|
|
6
|
+
* Use `ResponsivePanel` for tool panes and admin/detail flows that need the same
|
|
7
|
+
* content to work across compact mobile screens and wider desktop layouts.
|
|
8
|
+
*
|
|
9
|
+
* @readme
|
|
10
|
+
* @example Scrollable wide panel
|
|
11
|
+
* ```tsx
|
|
12
|
+
* <ResponsivePanel open title="APIs" size="wide" scroll="content">...</ResponsivePanel>
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
3
15
|
export declare const ResponsivePanel: (props: ResponsivePanelProps) => React.ReactElement | null;
|
|
4
16
|
//# sourceMappingURL=ResponsivePanel.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ResponsivePanel.d.ts","sourceRoot":"","sources":["../../../src/patterns/responsive-panel/ResponsivePanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"ResponsivePanel.d.ts","sourceRoot":"","sources":["../../../src/patterns/responsive-panel/ResponsivePanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAQ1B,OAAO,KAAK,EAAE,oBAAoB,EAA8C,MAAM,SAAS,CAAC;AA0IhG;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,eAAe,4DAA2C,CAAC"}
|
|
@@ -1,27 +1,92 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import { ScrollView, StyleSheet, View } from 'react-native';
|
|
2
3
|
import { Drawer } from '../../components/drawer';
|
|
3
4
|
import { Modal } from '../../components/modal';
|
|
4
5
|
import { withZoraThemeScope } from '../../theme/withZoraThemeScope';
|
|
5
6
|
import { Panel } from '../panel';
|
|
6
|
-
function
|
|
7
|
+
function resolvePanelWidth(size) {
|
|
8
|
+
switch (size) {
|
|
9
|
+
case 'compact':
|
|
10
|
+
return 300;
|
|
11
|
+
case 'wide':
|
|
12
|
+
return 420;
|
|
13
|
+
case 'extraWide':
|
|
14
|
+
return 560;
|
|
15
|
+
case 'default':
|
|
16
|
+
default:
|
|
17
|
+
return 360;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function resolveModalWidth(size) {
|
|
21
|
+
switch (size) {
|
|
22
|
+
case 'compact':
|
|
23
|
+
return 'narrow';
|
|
24
|
+
case 'wide':
|
|
25
|
+
case 'extraWide':
|
|
26
|
+
return 'wide';
|
|
27
|
+
case 'default':
|
|
28
|
+
return 'default';
|
|
29
|
+
default:
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function renderPanelBody(children, scroll) {
|
|
34
|
+
if (children == null)
|
|
35
|
+
return null;
|
|
36
|
+
if (scroll === 'content') {
|
|
37
|
+
return (<ScrollView contentContainerStyle={styles.scrollContent} keyboardShouldPersistTaps="handled" showsVerticalScrollIndicator style={styles.scrollBody}>
|
|
38
|
+
{children}
|
|
39
|
+
</ScrollView>);
|
|
40
|
+
}
|
|
41
|
+
return children;
|
|
42
|
+
}
|
|
43
|
+
function ResponsivePanelInner({ themeId: _themeId, mode: _mode, title, description, actions, footer, children, open, onOpenChange, side = 'right', desktopMode = 'inline', mobileMode = 'drawer', compact = true, size, scroll = 'none', testID, }) {
|
|
7
44
|
if (!open)
|
|
8
45
|
return null;
|
|
46
|
+
const body = renderPanelBody(children, scroll);
|
|
9
47
|
// For now, we assume desktopMode determines the rendering.
|
|
10
48
|
// In a real app, this would react to window size.
|
|
11
49
|
if (desktopMode === 'floating') {
|
|
12
50
|
if (mobileMode === 'modal') {
|
|
13
|
-
|
|
14
|
-
|
|
51
|
+
const modalWidth = resolveModalWidth(size);
|
|
52
|
+
return (<Modal description={description} footer={footer} onDismiss={() => onOpenChange(false)} testID={testID} title={title} visible={open} width={modalWidth}>
|
|
53
|
+
{body}
|
|
15
54
|
</Modal>);
|
|
16
55
|
}
|
|
17
56
|
return (<Drawer description={description} footer={footer} onDismiss={() => onOpenChange(false)} position={side} testID={testID} title={title} visible={open}>
|
|
18
|
-
{
|
|
57
|
+
{body}
|
|
19
58
|
</Drawer>);
|
|
20
59
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
{children}
|
|
60
|
+
const panel = (<Panel actions={actions} compact={compact} description={description} footer={footer} testID={testID} title={title}>
|
|
61
|
+
{body}
|
|
24
62
|
</Panel>);
|
|
63
|
+
if (size === undefined)
|
|
64
|
+
return panel;
|
|
65
|
+
return <View style={[styles.inlineSizedPanel, { width: resolvePanelWidth(size) }]}>{panel}</View>;
|
|
25
66
|
}
|
|
67
|
+
const styles = StyleSheet.create({
|
|
68
|
+
inlineSizedPanel: {
|
|
69
|
+
maxWidth: '100%',
|
|
70
|
+
},
|
|
71
|
+
scrollBody: {
|
|
72
|
+
flexGrow: 0,
|
|
73
|
+
maxHeight: '100%',
|
|
74
|
+
},
|
|
75
|
+
scrollContent: {
|
|
76
|
+
flexGrow: 1,
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
/***
|
|
80
|
+
* Adaptive secondary surface that can render as an inline panel, drawer, or modal.
|
|
81
|
+
*
|
|
82
|
+
* Use `ResponsivePanel` for tool panes and admin/detail flows that need the same
|
|
83
|
+
* content to work across compact mobile screens and wider desktop layouts.
|
|
84
|
+
*
|
|
85
|
+
* @readme
|
|
86
|
+
* @example Scrollable wide panel
|
|
87
|
+
* ```tsx
|
|
88
|
+
* <ResponsivePanel open title="APIs" size="wide" scroll="content">...</ResponsivePanel>
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
26
91
|
export const ResponsivePanel = withZoraThemeScope(ResponsivePanelInner);
|
|
27
92
|
//# sourceMappingURL=ResponsivePanel.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ResponsivePanel.js","sourceRoot":"","sources":["../../../src/patterns/responsive-panel/ResponsivePanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"ResponsivePanel.js","sourceRoot":"","sources":["../../../src/patterns/responsive-panel/ResponsivePanel.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from 'react';\nimport { ScrollView, StyleSheet, View } from 'react-native';\n\nimport { Drawer } from '../../components/drawer';\nimport { Modal } from '../../components/modal';\nimport type { ZoraContentWidth } from '../../internal/recipes';\nimport { withZoraThemeScope } from '../../theme/withZoraThemeScope';\nimport { Panel } from '../panel';\nimport type { ResponsivePanelProps, ResponsivePanelScroll, ResponsivePanelSize } from './types';\n\nfunction resolvePanelWidth(size: ResponsivePanelSize): number {\n switch (size) {\n case 'compact':\n return 300;\n case 'wide':\n return 420;\n case 'extraWide':\n return 560;\n case 'default':\n default:\n return 360;\n }\n}\n\nfunction resolveModalWidth(size: ResponsivePanelSize | undefined): ZoraContentWidth | undefined {\n switch (size) {\n case 'compact':\n return 'narrow';\n case 'wide':\n case 'extraWide':\n return 'wide';\n case 'default':\n return 'default';\n default:\n return undefined;\n }\n}\n\nfunction renderPanelBody(children: React.ReactNode, scroll: ResponsivePanelScroll) {\n if (children == null) return null;\n\n if (scroll === 'content') {\n return (\n <ScrollView\n contentContainerStyle={styles.scrollContent}\n keyboardShouldPersistTaps=\"handled\"\n showsVerticalScrollIndicator\n style={styles.scrollBody}\n >\n {children}\n </ScrollView>\n );\n }\n\n return children;\n}\n\nfunction ResponsivePanelInner({\n themeId: _themeId,\n mode: _mode,\n title,\n description,\n actions,\n footer,\n children,\n open,\n onOpenChange,\n side = 'right',\n desktopMode = 'inline',\n mobileMode = 'drawer',\n compact = true,\n size,\n scroll = 'none',\n testID,\n}: ResponsivePanelProps) {\n if (!open) return null;\n\n const body = renderPanelBody(children, scroll);\n\n // For now, we assume desktopMode determines the rendering.\n // In a real app, this would react to window size.\n if (desktopMode === 'floating') {\n if (mobileMode === 'modal') {\n const modalWidth = resolveModalWidth(size);\n\n return (\n <Modal\n description={description}\n footer={footer}\n onDismiss={() => onOpenChange(false)}\n testID={testID}\n title={title}\n visible={open}\n width={modalWidth}\n >\n {body}\n </Modal>\n );\n }\n\n return (\n <Drawer\n description={description}\n footer={footer}\n onDismiss={() => onOpenChange(false)}\n position={side}\n testID={testID}\n title={title}\n visible={open}\n >\n {body}\n </Drawer>\n );\n }\n\n const panel = (\n <Panel\n actions={actions}\n compact={compact}\n description={description}\n footer={footer}\n testID={testID}\n title={title}\n >\n {body}\n </Panel>\n );\n\n if (size === undefined) return panel;\n\n return <View style={[styles.inlineSizedPanel, { width: resolvePanelWidth(size) }]}>{panel}</View>;\n}\n\nconst styles = StyleSheet.create({\n inlineSizedPanel: {\n maxWidth: '100%',\n },\n scrollBody: {\n flexGrow: 0,\n maxHeight: '100%',\n },\n scrollContent: {\n flexGrow: 1,\n },\n});\n\n/***\n * Adaptive secondary surface that can render as an inline panel, drawer, or modal.\n *\n * Use `ResponsivePanel` for tool panes and admin/detail flows that need the same\n * content to work across compact mobile screens and wider desktop layouts.\n *\n * @readme\n * @example Scrollable wide panel\n * ```tsx\n * <ResponsivePanel open title=\"APIs\" size=\"wide\" scroll=\"content\">...</ResponsivePanel>\n * ```\n */\nexport const ResponsivePanel = withZoraThemeScope(ResponsivePanelInner);\n"]}
|
|
@@ -3,6 +3,8 @@ import type { ZoraBaseProps } from '../../theme/ZoraBaseProps';
|
|
|
3
3
|
export type ResponsivePanelSide = 'left' | 'right';
|
|
4
4
|
export type ResponsivePanelDesktopMode = 'inline' | 'floating';
|
|
5
5
|
export type ResponsivePanelMobileMode = 'drawer' | 'modal';
|
|
6
|
+
export type ResponsivePanelSize = 'compact' | 'default' | 'wide' | 'extraWide';
|
|
7
|
+
export type ResponsivePanelScroll = 'none' | 'content';
|
|
6
8
|
export interface ResponsivePanelProps extends ZoraBaseProps {
|
|
7
9
|
title?: React.ReactNode;
|
|
8
10
|
description?: React.ReactNode;
|
|
@@ -15,5 +17,7 @@ export interface ResponsivePanelProps extends ZoraBaseProps {
|
|
|
15
17
|
desktopMode?: ResponsivePanelDesktopMode;
|
|
16
18
|
mobileMode?: ResponsivePanelMobileMode;
|
|
17
19
|
compact?: boolean;
|
|
20
|
+
size?: ResponsivePanelSize;
|
|
21
|
+
scroll?: ResponsivePanelScroll;
|
|
18
22
|
}
|
|
19
23
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/patterns/responsive-panel/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE/D,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,OAAO,CAAC;AACnD,MAAM,MAAM,0BAA0B,GAAG,QAAQ,GAAG,UAAU,CAAC;AAC/D,MAAM,MAAM,yBAAyB,GAAG,QAAQ,GAAG,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/patterns/responsive-panel/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE/D,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,OAAO,CAAC;AACnD,MAAM,MAAM,0BAA0B,GAAG,QAAQ,GAAG,UAAU,CAAC;AAC/D,MAAM,MAAM,yBAAyB,GAAG,QAAQ,GAAG,OAAO,CAAC;AAC3D,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,SAAS,GAAG,MAAM,GAAG,WAAW,CAAC;AAC/E,MAAM,MAAM,qBAAqB,GAAG,MAAM,GAAG,SAAS,CAAC;AAEvD,MAAM,WAAW,oBAAqB,SAAQ,aAAa;IACzD,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC9B,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,IAAI,CAAC,EAAE,mBAAmB,CAAC;IAC3B,WAAW,CAAC,EAAE,0BAA0B,CAAC;IACzC,UAAU,CAAC,EAAE,yBAAyB,CAAC;IACvC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,mBAAmB,CAAC;IAC3B,MAAM,CAAC,EAAE,qBAAqB,CAAC;CAChC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/patterns/responsive-panel/types.ts"],"names":[],"mappings":"","sourcesContent":["import type React from 'react';\n\nimport type { ZoraBaseProps } from '../../theme/ZoraBaseProps';\n\nexport type ResponsivePanelSide = 'left' | 'right';\nexport type ResponsivePanelDesktopMode = 'inline' | 'floating';\nexport type ResponsivePanelMobileMode = 'drawer' | 'modal';\n\nexport interface ResponsivePanelProps extends ZoraBaseProps {\n title?: React.ReactNode;\n description?: React.ReactNode;\n actions?: React.ReactNode;\n footer?: React.ReactNode;\n children?: React.ReactNode;\n open: boolean;\n onOpenChange: (open: boolean) => void;\n side?: ResponsivePanelSide;\n desktopMode?: ResponsivePanelDesktopMode;\n mobileMode?: ResponsivePanelMobileMode;\n compact?: boolean;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/patterns/responsive-panel/types.ts"],"names":[],"mappings":"","sourcesContent":["import type React from 'react';\n\nimport type { ZoraBaseProps } from '../../theme/ZoraBaseProps';\n\nexport type ResponsivePanelSide = 'left' | 'right';\nexport type ResponsivePanelDesktopMode = 'inline' | 'floating';\nexport type ResponsivePanelMobileMode = 'drawer' | 'modal';\nexport type ResponsivePanelSize = 'compact' | 'default' | 'wide' | 'extraWide';\nexport type ResponsivePanelScroll = 'none' | 'content';\n\nexport interface ResponsivePanelProps extends ZoraBaseProps {\n title?: React.ReactNode;\n description?: React.ReactNode;\n actions?: React.ReactNode;\n footer?: React.ReactNode;\n children?: React.ReactNode;\n open: boolean;\n onOpenChange: (open: boolean) => void;\n side?: ResponsivePanelSide;\n desktopMode?: ResponsivePanelDesktopMode;\n mobileMode?: ResponsivePanelMobileMode;\n compact?: boolean;\n size?: ResponsivePanelSize;\n scroll?: ResponsivePanelScroll;\n}\n"]}
|
|
@@ -5,5 +5,17 @@ export interface ZoraProviderProps {
|
|
|
5
5
|
theme?: ZoraTheme;
|
|
6
6
|
initialMode?: ZoraThemeMode;
|
|
7
7
|
}
|
|
8
|
+
/***
|
|
9
|
+
* Installs the ZORA theme runtime and underlying Surface theme provider.
|
|
10
|
+
*
|
|
11
|
+
* Wrap an app with `ZoraProvider` once near the root so components, patterns,
|
|
12
|
+
* layouts, and theme hooks resolve the same design tokens and color mode.
|
|
13
|
+
*
|
|
14
|
+
* @readme
|
|
15
|
+
* @example App provider
|
|
16
|
+
* ```tsx
|
|
17
|
+
* <ZoraProvider initialMode="light"><App /></ZoraProvider>
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
8
20
|
export declare function ZoraProvider({ children, theme, initialMode, }: ZoraProviderProps): React.JSX.Element;
|
|
9
21
|
//# sourceMappingURL=ZoraProvider.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ZoraProvider.d.ts","sourceRoot":"","sources":["../../src/theme/ZoraProvider.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAIxD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,WAAW,CAAC,EAAE,aAAa,CAAC;CAC7B;AAED,wBAAgB,YAAY,CAAC,EAC3B,QAAQ,EACR,KAAwB,EACxB,WAAqB,GACtB,EAAE,iBAAiB,qBAUnB"}
|
|
1
|
+
{"version":3,"file":"ZoraProvider.d.ts","sourceRoot":"","sources":["../../src/theme/ZoraProvider.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAIxD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,WAAW,CAAC,EAAE,aAAa,CAAC;CAC7B;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,EAC3B,QAAQ,EACR,KAAwB,EACxB,WAAqB,GACtB,EAAE,iBAAiB,qBAUnB"}
|
|
@@ -3,6 +3,18 @@ import React from 'react';
|
|
|
3
3
|
import { createZoraThemeConfig } from './createZoraThemeConfig';
|
|
4
4
|
import { zoraDefaultTheme } from './zoraDefaultTheme';
|
|
5
5
|
import { ZoraThemeRuntimeContext } from './ZoraThemeRuntimeContext';
|
|
6
|
+
/***
|
|
7
|
+
* Installs the ZORA theme runtime and underlying Surface theme provider.
|
|
8
|
+
*
|
|
9
|
+
* Wrap an app with `ZoraProvider` once near the root so components, patterns,
|
|
10
|
+
* layouts, and theme hooks resolve the same design tokens and color mode.
|
|
11
|
+
*
|
|
12
|
+
* @readme
|
|
13
|
+
* @example App provider
|
|
14
|
+
* ```tsx
|
|
15
|
+
* <ZoraProvider initialMode="light"><App /></ZoraProvider>
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
6
18
|
export function ZoraProvider({ children, theme = zoraDefaultTheme, initialMode = 'light', }) {
|
|
7
19
|
const runtimeValue = React.useMemo(() => ({ sourceTheme: theme, themeId: theme.id }), [theme]);
|
|
8
20
|
return (<ZoraThemeRuntimeContext.Provider value={runtimeValue}>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ZoraProvider.js","sourceRoot":"","sources":["../../src/theme/ZoraProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAQpE,MAAM,UAAU,YAAY,CAAC,EAC3B,QAAQ,EACR,KAAK,GAAG,gBAAgB,EACxB,WAAW,GAAG,OAAO,GACH;IAClB,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IAE/F,OAAO,CACL,CAAC,uBAAuB,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CACpD;MAAA,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,WAAW,CAAC,CACnF;QAAA,CAAC,QAAQ,CACX;MAAA,EAAE,aAAa,CACjB;IAAA,EAAE,uBAAuB,CAAC,QAAQ,CAAC,CACpC,CAAC;AACJ,CAAC","sourcesContent":["import { ThemeProvider } from '@ankhorage/surface';\nimport React from 'react';\n\nimport { createZoraThemeConfig } from './createZoraThemeConfig';\nimport type { ZoraTheme, ZoraThemeMode } from './types';\nimport { zoraDefaultTheme } from './zoraDefaultTheme';\nimport { ZoraThemeRuntimeContext } from './ZoraThemeRuntimeContext';\n\nexport interface ZoraProviderProps {\n children: React.ReactNode;\n theme?: ZoraTheme;\n initialMode?: ZoraThemeMode;\n}\n\nexport function ZoraProvider({\n children,\n theme = zoraDefaultTheme,\n initialMode = 'light',\n}: ZoraProviderProps) {\n const runtimeValue = React.useMemo(() => ({ sourceTheme: theme, themeId: theme.id }), [theme]);\n\n return (\n <ZoraThemeRuntimeContext.Provider value={runtimeValue}>\n <ThemeProvider initialConfig={createZoraThemeConfig(theme)} initialMode={initialMode}>\n {children}\n </ThemeProvider>\n </ZoraThemeRuntimeContext.Provider>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ZoraProvider.js","sourceRoot":"","sources":["../../src/theme/ZoraProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAQpE;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,YAAY,CAAC,EAC3B,QAAQ,EACR,KAAK,GAAG,gBAAgB,EACxB,WAAW,GAAG,OAAO,GACH;IAClB,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IAE/F,OAAO,CACL,CAAC,uBAAuB,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CACpD;MAAA,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,WAAW,CAAC,CACnF;QAAA,CAAC,QAAQ,CACX;MAAA,EAAE,aAAa,CACjB;IAAA,EAAE,uBAAuB,CAAC,QAAQ,CAAC,CACpC,CAAC;AACJ,CAAC","sourcesContent":["import { ThemeProvider } from '@ankhorage/surface';\nimport React from 'react';\n\nimport { createZoraThemeConfig } from './createZoraThemeConfig';\nimport type { ZoraTheme, ZoraThemeMode } from './types';\nimport { zoraDefaultTheme } from './zoraDefaultTheme';\nimport { ZoraThemeRuntimeContext } from './ZoraThemeRuntimeContext';\n\nexport interface ZoraProviderProps {\n children: React.ReactNode;\n theme?: ZoraTheme;\n initialMode?: ZoraThemeMode;\n}\n\n/***\n * Installs the ZORA theme runtime and underlying Surface theme provider.\n *\n * Wrap an app with `ZoraProvider` once near the root so components, patterns,\n * layouts, and theme hooks resolve the same design tokens and color mode.\n *\n * @readme\n * @example App provider\n * ```tsx\n * <ZoraProvider initialMode=\"light\"><App /></ZoraProvider>\n * ```\n */\nexport function ZoraProvider({\n children,\n theme = zoraDefaultTheme,\n initialMode = 'light',\n}: ZoraProviderProps) {\n const runtimeValue = React.useMemo(() => ({ sourceTheme: theme, themeId: theme.id }), [theme]);\n\n return (\n <ZoraThemeRuntimeContext.Provider value={runtimeValue}>\n <ThemeProvider initialConfig={createZoraThemeConfig(theme)} initialMode={initialMode}>\n {children}\n </ThemeProvider>\n </ZoraThemeRuntimeContext.Provider>\n );\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ankhorage/zora",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "2.5.
|
|
4
|
+
"version": "2.5.2",
|
|
5
5
|
"description": "Opinionated React Native and React Native Web UI kit built on @ankhorage/surface.",
|
|
6
6
|
"homepage": "https://github.com/ankhorage/zora#readme",
|
|
7
7
|
"bugs": {
|
|
@@ -20,4 +20,16 @@ function ButtonInner({
|
|
|
20
20
|
);
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
/***
|
|
24
|
+
* Theme-aware action control for primary, secondary, destructive, and neutral actions.
|
|
25
|
+
*
|
|
26
|
+
* Use `Button` for explicit user actions that should follow ZORA's semantic color,
|
|
27
|
+
* variant, and size recipes across React Native and React Native Web.
|
|
28
|
+
*
|
|
29
|
+
* @readme
|
|
30
|
+
* @example Basic action
|
|
31
|
+
* ```tsx
|
|
32
|
+
* <Button color="primary" variant="solid" onPress={save}>Save</Button>
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
23
35
|
export const Button = withZoraThemeScope(ButtonInner);
|
|
@@ -70,4 +70,16 @@ function CardInner({
|
|
|
70
70
|
);
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
+
/***
|
|
74
|
+
* Structured content container with built-in heading, description, actions, and footer slots.
|
|
75
|
+
*
|
|
76
|
+
* Use `Card` for reusable content blocks that should inherit ZORA spacing,
|
|
77
|
+
* radius, tone, and responsive header layout without hand-assembling primitives.
|
|
78
|
+
*
|
|
79
|
+
* @readme
|
|
80
|
+
* @example Content card
|
|
81
|
+
* ```tsx
|
|
82
|
+
* <Card title="Project" description="Latest activity">...</Card>
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
73
85
|
export const Card = withZoraThemeScope(CardInner);
|
|
@@ -91,4 +91,16 @@ function HeadingInner({
|
|
|
91
91
|
);
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
+
/***
|
|
95
|
+
* Structured title primitive for accessible page, section, and card headings.
|
|
96
|
+
*
|
|
97
|
+
* `Heading` gives consumers a ZORA-owned title API with semantic levels,
|
|
98
|
+
* responsive sizes, and theme-aware emphasis while preserving header semantics.
|
|
99
|
+
*
|
|
100
|
+
* @readme
|
|
101
|
+
* @example Section title
|
|
102
|
+
* ```tsx
|
|
103
|
+
* <Heading level={2} size="xl">Account settings</Heading>
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
94
106
|
export const Heading = withZoraThemeScope(HeadingInner);
|
|
@@ -62,4 +62,16 @@ function InputInner({
|
|
|
62
62
|
);
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
/***
|
|
66
|
+
* Theme-aware text input with semantic sizing and optional leading/trailing icon slots.
|
|
67
|
+
*
|
|
68
|
+
* Use `Input` for single-line form controls that need ZORA styling, disabled/read-only
|
|
69
|
+
* handling, and accessible trailing actions without dropping into Surface directly.
|
|
70
|
+
*
|
|
71
|
+
* @readme
|
|
72
|
+
* @example Search input
|
|
73
|
+
* ```tsx
|
|
74
|
+
* <Input placeholder="Search" leadingIcon={{ name: 'search-outline' }} />
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
65
77
|
export const Input = withZoraThemeScope(InputInner);
|
|
@@ -88,4 +88,16 @@ function TextInner({
|
|
|
88
88
|
);
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
+
/***
|
|
92
|
+
* Structured copy primitive for theme-aware app text.
|
|
93
|
+
*
|
|
94
|
+
* `Text` owns normal body, caption, label, code, and supporting-copy variants so
|
|
95
|
+
* consumers do not need to import lower-level Surface typography directly.
|
|
96
|
+
*
|
|
97
|
+
* @readme
|
|
98
|
+
* @example Muted supporting copy
|
|
99
|
+
* ```tsx
|
|
100
|
+
* <Text variant="bodySmall" emphasis="muted">Updated just now</Text>
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
91
103
|
export const Text = withZoraThemeScope(TextInner);
|
package/src/index.ts
CHANGED
|
@@ -288,7 +288,9 @@ export type {
|
|
|
288
288
|
ResponsivePanelDesktopMode,
|
|
289
289
|
ResponsivePanelMobileMode,
|
|
290
290
|
ResponsivePanelProps,
|
|
291
|
+
ResponsivePanelScroll,
|
|
291
292
|
ResponsivePanelSide,
|
|
293
|
+
ResponsivePanelSize,
|
|
292
294
|
} from './patterns/responsive-panel';
|
|
293
295
|
export { ResponsivePanel } from './patterns/responsive-panel';
|
|
294
296
|
export type { SectionHeaderProps } from './patterns/section-header';
|
|
@@ -33,6 +33,18 @@ function AppShellInner({
|
|
|
33
33
|
);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
/***
|
|
37
|
+
* Root application shell with stable header, content, footer, and overlay slots.
|
|
38
|
+
*
|
|
39
|
+
* `AppShell` provides the top-level layout frame for cross-platform apps while
|
|
40
|
+
* leaving navigation, toolbars, and overlays composable through explicit slots.
|
|
41
|
+
*
|
|
42
|
+
* @readme
|
|
43
|
+
* @example App frame
|
|
44
|
+
* ```tsx
|
|
45
|
+
* <AppShell header={<AppBar title="Dashboard" />}>...</AppShell>
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
36
48
|
export const AppShell = withZoraThemeScope(AppShellInner);
|
|
37
49
|
|
|
38
50
|
const styles = StyleSheet.create({
|
|
@@ -55,4 +55,16 @@ function EmptyStateInner({
|
|
|
55
55
|
);
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
/***
|
|
59
|
+
* Reusable fallback state for empty lists, missing data, or first-run experiences.
|
|
60
|
+
*
|
|
61
|
+
* `EmptyState` combines concise copy with optional primary and secondary actions
|
|
62
|
+
* so apps can guide users without custom card and button wiring.
|
|
63
|
+
*
|
|
64
|
+
* @readme
|
|
65
|
+
* @example Empty project list
|
|
66
|
+
* ```tsx
|
|
67
|
+
* <EmptyState title="No projects yet" primaryAction={{ label: 'Create project', onPress }} />
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
58
70
|
export const EmptyState = withZoraThemeScope(EmptyStateInner);
|
|
@@ -1,10 +1,59 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import { ScrollView, StyleSheet, View } from 'react-native';
|
|
2
3
|
|
|
3
4
|
import { Drawer } from '../../components/drawer';
|
|
4
5
|
import { Modal } from '../../components/modal';
|
|
6
|
+
import type { ZoraContentWidth } from '../../internal/recipes';
|
|
5
7
|
import { withZoraThemeScope } from '../../theme/withZoraThemeScope';
|
|
6
8
|
import { Panel } from '../panel';
|
|
7
|
-
import type { ResponsivePanelProps } from './types';
|
|
9
|
+
import type { ResponsivePanelProps, ResponsivePanelScroll, ResponsivePanelSize } from './types';
|
|
10
|
+
|
|
11
|
+
function resolvePanelWidth(size: ResponsivePanelSize): number {
|
|
12
|
+
switch (size) {
|
|
13
|
+
case 'compact':
|
|
14
|
+
return 300;
|
|
15
|
+
case 'wide':
|
|
16
|
+
return 420;
|
|
17
|
+
case 'extraWide':
|
|
18
|
+
return 560;
|
|
19
|
+
case 'default':
|
|
20
|
+
default:
|
|
21
|
+
return 360;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function resolveModalWidth(size: ResponsivePanelSize | undefined): ZoraContentWidth | undefined {
|
|
26
|
+
switch (size) {
|
|
27
|
+
case 'compact':
|
|
28
|
+
return 'narrow';
|
|
29
|
+
case 'wide':
|
|
30
|
+
case 'extraWide':
|
|
31
|
+
return 'wide';
|
|
32
|
+
case 'default':
|
|
33
|
+
return 'default';
|
|
34
|
+
default:
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function renderPanelBody(children: React.ReactNode, scroll: ResponsivePanelScroll) {
|
|
40
|
+
if (children == null) return null;
|
|
41
|
+
|
|
42
|
+
if (scroll === 'content') {
|
|
43
|
+
return (
|
|
44
|
+
<ScrollView
|
|
45
|
+
contentContainerStyle={styles.scrollContent}
|
|
46
|
+
keyboardShouldPersistTaps="handled"
|
|
47
|
+
showsVerticalScrollIndicator
|
|
48
|
+
style={styles.scrollBody}
|
|
49
|
+
>
|
|
50
|
+
{children}
|
|
51
|
+
</ScrollView>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return children;
|
|
56
|
+
}
|
|
8
57
|
|
|
9
58
|
function ResponsivePanelInner({
|
|
10
59
|
themeId: _themeId,
|
|
@@ -20,14 +69,20 @@ function ResponsivePanelInner({
|
|
|
20
69
|
desktopMode = 'inline',
|
|
21
70
|
mobileMode = 'drawer',
|
|
22
71
|
compact = true,
|
|
72
|
+
size,
|
|
73
|
+
scroll = 'none',
|
|
23
74
|
testID,
|
|
24
75
|
}: ResponsivePanelProps) {
|
|
25
76
|
if (!open) return null;
|
|
26
77
|
|
|
78
|
+
const body = renderPanelBody(children, scroll);
|
|
79
|
+
|
|
27
80
|
// For now, we assume desktopMode determines the rendering.
|
|
28
81
|
// In a real app, this would react to window size.
|
|
29
82
|
if (desktopMode === 'floating') {
|
|
30
83
|
if (mobileMode === 'modal') {
|
|
84
|
+
const modalWidth = resolveModalWidth(size);
|
|
85
|
+
|
|
31
86
|
return (
|
|
32
87
|
<Modal
|
|
33
88
|
description={description}
|
|
@@ -36,8 +91,9 @@ function ResponsivePanelInner({
|
|
|
36
91
|
testID={testID}
|
|
37
92
|
title={title}
|
|
38
93
|
visible={open}
|
|
94
|
+
width={modalWidth}
|
|
39
95
|
>
|
|
40
|
-
{
|
|
96
|
+
{body}
|
|
41
97
|
</Modal>
|
|
42
98
|
);
|
|
43
99
|
}
|
|
@@ -52,13 +108,12 @@ function ResponsivePanelInner({
|
|
|
52
108
|
title={title}
|
|
53
109
|
visible={open}
|
|
54
110
|
>
|
|
55
|
-
{
|
|
111
|
+
{body}
|
|
56
112
|
</Drawer>
|
|
57
113
|
);
|
|
58
114
|
}
|
|
59
115
|
|
|
60
|
-
|
|
61
|
-
return (
|
|
116
|
+
const panel = (
|
|
62
117
|
<Panel
|
|
63
118
|
actions={actions}
|
|
64
119
|
compact={compact}
|
|
@@ -67,9 +122,38 @@ function ResponsivePanelInner({
|
|
|
67
122
|
testID={testID}
|
|
68
123
|
title={title}
|
|
69
124
|
>
|
|
70
|
-
{
|
|
125
|
+
{body}
|
|
71
126
|
</Panel>
|
|
72
127
|
);
|
|
128
|
+
|
|
129
|
+
if (size === undefined) return panel;
|
|
130
|
+
|
|
131
|
+
return <View style={[styles.inlineSizedPanel, { width: resolvePanelWidth(size) }]}>{panel}</View>;
|
|
73
132
|
}
|
|
74
133
|
|
|
134
|
+
const styles = StyleSheet.create({
|
|
135
|
+
inlineSizedPanel: {
|
|
136
|
+
maxWidth: '100%',
|
|
137
|
+
},
|
|
138
|
+
scrollBody: {
|
|
139
|
+
flexGrow: 0,
|
|
140
|
+
maxHeight: '100%',
|
|
141
|
+
},
|
|
142
|
+
scrollContent: {
|
|
143
|
+
flexGrow: 1,
|
|
144
|
+
},
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
/***
|
|
148
|
+
* Adaptive secondary surface that can render as an inline panel, drawer, or modal.
|
|
149
|
+
*
|
|
150
|
+
* Use `ResponsivePanel` for tool panes and admin/detail flows that need the same
|
|
151
|
+
* content to work across compact mobile screens and wider desktop layouts.
|
|
152
|
+
*
|
|
153
|
+
* @readme
|
|
154
|
+
* @example Scrollable wide panel
|
|
155
|
+
* ```tsx
|
|
156
|
+
* <ResponsivePanel open title="APIs" size="wide" scroll="content">...</ResponsivePanel>
|
|
157
|
+
* ```
|
|
158
|
+
*/
|
|
75
159
|
export const ResponsivePanel = withZoraThemeScope(ResponsivePanelInner);
|
|
@@ -5,6 +5,8 @@ import type { ZoraBaseProps } from '../../theme/ZoraBaseProps';
|
|
|
5
5
|
export type ResponsivePanelSide = 'left' | 'right';
|
|
6
6
|
export type ResponsivePanelDesktopMode = 'inline' | 'floating';
|
|
7
7
|
export type ResponsivePanelMobileMode = 'drawer' | 'modal';
|
|
8
|
+
export type ResponsivePanelSize = 'compact' | 'default' | 'wide' | 'extraWide';
|
|
9
|
+
export type ResponsivePanelScroll = 'none' | 'content';
|
|
8
10
|
|
|
9
11
|
export interface ResponsivePanelProps extends ZoraBaseProps {
|
|
10
12
|
title?: React.ReactNode;
|
|
@@ -18,4 +20,6 @@ export interface ResponsivePanelProps extends ZoraBaseProps {
|
|
|
18
20
|
desktopMode?: ResponsivePanelDesktopMode;
|
|
19
21
|
mobileMode?: ResponsivePanelMobileMode;
|
|
20
22
|
compact?: boolean;
|
|
23
|
+
size?: ResponsivePanelSize;
|
|
24
|
+
scroll?: ResponsivePanelScroll;
|
|
21
25
|
}
|
|
@@ -12,6 +12,18 @@ export interface ZoraProviderProps {
|
|
|
12
12
|
initialMode?: ZoraThemeMode;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
/***
|
|
16
|
+
* Installs the ZORA theme runtime and underlying Surface theme provider.
|
|
17
|
+
*
|
|
18
|
+
* Wrap an app with `ZoraProvider` once near the root so components, patterns,
|
|
19
|
+
* layouts, and theme hooks resolve the same design tokens and color mode.
|
|
20
|
+
*
|
|
21
|
+
* @readme
|
|
22
|
+
* @example App provider
|
|
23
|
+
* ```tsx
|
|
24
|
+
* <ZoraProvider initialMode="light"><App /></ZoraProvider>
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
15
27
|
export function ZoraProvider({
|
|
16
28
|
children,
|
|
17
29
|
theme = zoraDefaultTheme,
|