@ankhorage/zora 0.5.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.5.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 1f6d9a7: Fix infinite render loop in Modal and Drawer
8
+
9
+ Stabilizes onDismiss handling to prevent repeated state updates causing
10
+ "Maximum update depth exceeded" errors when opening overlays.
11
+
3
12
  ## 0.5.0
4
13
 
5
14
  ### Minor Changes
package/README.md CHANGED
@@ -44,8 +44,8 @@ export function App() {
44
44
  return (
45
45
  <ZoraProvider>
46
46
  <AppShell
47
- topbar={
48
- <Toolbar position="inline">
47
+ header={
48
+ <Toolbar>
49
49
  <ToolbarAction icon={{ name: 'menu-outline' }} label="Menu" />
50
50
  </Toolbar>
51
51
  }
@@ -1,4 +1,4 @@
1
1
  import React from 'react';
2
2
  import type { DrawerProps } from './types';
3
- export declare function Drawer({ children, title, description, footer, ...props }: DrawerProps): React.JSX.Element;
3
+ export declare function Drawer({ children, title, description, footer, onDismiss, ...props }: DrawerProps): React.JSX.Element;
4
4
  //# sourceMappingURL=Drawer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Drawer.d.ts","sourceRoot":"","sources":["../../../src/components/drawer/Drawer.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE3C,wBAAgB,MAAM,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,KAAK,EAAE,EAAE,WAAW,qBAqBrF"}
1
+ {"version":3,"file":"Drawer.d.ts","sourceRoot":"","sources":["../../../src/components/drawer/Drawer.tsx"],"names":[],"mappings":"AACA,OAAO,KAAyC,MAAM,OAAO,CAAC;AAE9D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAc3C,wBAAgB,MAAM,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,WAAW,qBAsBhG"}
@@ -1,8 +1,18 @@
1
1
  import { Box, Drawer as SurfaceDrawer, Heading, Stack, Text } from '@ankhorage/surface';
2
- import React from 'react';
3
- export function Drawer({ children, title, description, footer, ...props }) {
2
+ import React, { useCallback, useEffect, useRef } from 'react';
3
+ function useStableCallback(callback) {
4
+ const callbackRef = useRef(callback);
5
+ useEffect(() => {
6
+ callbackRef.current = callback;
7
+ }, [callback]);
8
+ return useCallback(() => {
9
+ callbackRef.current?.();
10
+ }, []);
11
+ }
12
+ export function Drawer({ children, title, description, footer, onDismiss, ...props }) {
4
13
  const hasHeader = title != null || description != null;
5
- return (<SurfaceDrawer {...props}>
14
+ const stableOnDismiss = useStableCallback(onDismiss);
15
+ return (<SurfaceDrawer {...props} onDismiss={stableOnDismiss}>
6
16
  <Stack gap="m">
7
17
  {hasHeader ? (<Stack gap="xs">
8
18
  {title ? <Heading level={3}>{title}</Heading> : null}
@@ -1 +1 @@
1
- {"version":3,"file":"Drawer.js","sourceRoot":"","sources":["../../../src/components/drawer/Drawer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,IAAI,aAAa,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AACxF,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,MAAM,UAAU,MAAM,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,KAAK,EAAe;IACpF,MAAM,SAAS,GAAG,KAAK,IAAI,IAAI,IAAI,WAAW,IAAI,IAAI,CAAC;IAEvD,OAAO,CACL,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC,CACvB;MAAA,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CACZ;QAAA,CAAC,SAAS,CAAC,CAAC,CAAC,CACX,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CACb;YAAA,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CACpD;YAAA,CAAC,WAAW,CAAC,CAAC,CAAC,CACb,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,CACpC;gBAAA,CAAC,WAAW,CACd;cAAA,EAAE,IAAI,CAAC,CACR,CAAC,CAAC,CAAC,IAAI,CACV;UAAA,EAAE,KAAK,CAAC,CACT,CAAC,CAAC,CAAC,IAAI,CACR;QAAA,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CACjD;QAAA,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAC9C;MAAA,EAAE,KAAK,CACT;IAAA,EAAE,aAAa,CAAC,CACjB,CAAC;AACJ,CAAC","sourcesContent":["import { Box, Drawer as SurfaceDrawer, Heading, Stack, Text } from '@ankhorage/surface';\nimport React from 'react';\n\nimport type { DrawerProps } from './types';\n\nexport function Drawer({ children, title, description, footer, ...props }: DrawerProps) {\n const hasHeader = title != null || description != null;\n\n return (\n <SurfaceDrawer {...props}>\n <Stack gap=\"m\">\n {hasHeader ? (\n <Stack gap=\"xs\">\n {title ? <Heading level={3}>{title}</Heading> : null}\n {description ? (\n <Text tone=\"muted\" variant=\"bodySmall\">\n {description}\n </Text>\n ) : null}\n </Stack>\n ) : null}\n {children ? <Box flex={1}>{children}</Box> : null}\n {footer ? <Box pt=\"xs\">{footer}</Box> : null}\n </Stack>\n </SurfaceDrawer>\n );\n}\n"]}
1
+ {"version":3,"file":"Drawer.js","sourceRoot":"","sources":["../../../src/components/drawer/Drawer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,IAAI,aAAa,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AACxF,OAAO,KAAK,EAAE,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAI9D,SAAS,iBAAiB,CAAC,QAAkC;IAC3D,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;IAErC,SAAS,CAAC,GAAG,EAAE;QACb,WAAW,CAAC,OAAO,GAAG,QAAQ,CAAC;IACjC,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEf,OAAO,WAAW,CAAC,GAAG,EAAE;QACtB,WAAW,CAAC,OAAO,EAAE,EAAE,CAAC;IAC1B,CAAC,EAAE,EAAE,CAAC,CAAC;AACT,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,KAAK,EAAe;IAC/F,MAAM,SAAS,GAAG,KAAK,IAAI,IAAI,IAAI,WAAW,IAAI,IAAI,CAAC;IACvD,MAAM,eAAe,GAAG,iBAAiB,CAAC,SAAS,CAAC,CAAC;IAErD,OAAO,CACL,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC,CAAC,SAAS,CAAC,CAAC,eAAe,CAAC,CACnD;MAAA,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CACZ;QAAA,CAAC,SAAS,CAAC,CAAC,CAAC,CACX,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CACb;YAAA,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CACpD;YAAA,CAAC,WAAW,CAAC,CAAC,CAAC,CACb,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,CACpC;gBAAA,CAAC,WAAW,CACd;cAAA,EAAE,IAAI,CAAC,CACR,CAAC,CAAC,CAAC,IAAI,CACV;UAAA,EAAE,KAAK,CAAC,CACT,CAAC,CAAC,CAAC,IAAI,CACR;QAAA,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CACjD;QAAA,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAC9C;MAAA,EAAE,KAAK,CACT;IAAA,EAAE,aAAa,CAAC,CACjB,CAAC;AACJ,CAAC","sourcesContent":["import { Box, Drawer as SurfaceDrawer, Heading, Stack, Text } from '@ankhorage/surface';\nimport React, { useCallback, useEffect, useRef } from 'react';\n\nimport type { DrawerProps } from './types';\n\nfunction useStableCallback(callback: (() => void) | undefined): (() => void) | undefined {\n const callbackRef = useRef(callback);\n\n useEffect(() => {\n callbackRef.current = callback;\n }, [callback]);\n\n return useCallback(() => {\n callbackRef.current?.();\n }, []);\n}\n\nexport function Drawer({ children, title, description, footer, onDismiss, ...props }: DrawerProps) {\n const hasHeader = title != null || description != null;\n const stableOnDismiss = useStableCallback(onDismiss);\n\n return (\n <SurfaceDrawer {...props} onDismiss={stableOnDismiss}>\n <Stack gap=\"m\">\n {hasHeader ? (\n <Stack gap=\"xs\">\n {title ? <Heading level={3}>{title}</Heading> : null}\n {description ? (\n <Text tone=\"muted\" variant=\"bodySmall\">\n {description}\n </Text>\n ) : null}\n </Stack>\n ) : null}\n {children ? <Box flex={1}>{children}</Box> : null}\n {footer ? <Box pt=\"xs\">{footer}</Box> : null}\n </Stack>\n </SurfaceDrawer>\n );\n}\n"]}
@@ -1,4 +1,4 @@
1
1
  import React from 'react';
2
2
  import type { ModalProps } from './types';
3
- export declare function Modal({ children, title, description, footer, width, ...props }: ModalProps): React.JSX.Element;
3
+ export declare function Modal({ children, title, description, footer, width, onDismiss, ...props }: ModalProps): React.JSX.Element;
4
4
  //# sourceMappingURL=Modal.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Modal.d.ts","sourceRoot":"","sources":["../../../src/components/modal/Modal.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE1C,wBAAgB,KAAK,CAAC,EACpB,QAAQ,EACR,KAAK,EACL,WAAW,EACX,MAAM,EACN,KAAiB,EACjB,GAAG,KAAK,EACT,EAAE,UAAU,qBAuBZ"}
1
+ {"version":3,"file":"Modal.d.ts","sourceRoot":"","sources":["../../../src/components/modal/Modal.tsx"],"names":[],"mappings":"AACA,OAAO,KAAyC,MAAM,OAAO,CAAC;AAG9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAc1C,wBAAgB,KAAK,CAAC,EACpB,QAAQ,EACR,KAAK,EACL,WAAW,EACX,MAAM,EACN,KAAiB,EACjB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,UAAU,qBAwBZ"}
@@ -1,9 +1,19 @@
1
1
  import { Box, Heading, Modal as SurfaceModal, Stack, Text } from '@ankhorage/surface';
2
- import React from 'react';
2
+ import React, { useCallback, useEffect, useRef } from 'react';
3
3
  import { resolveDialogWidth } from '../../internal/recipes';
4
- export function Modal({ children, title, description, footer, width = 'default', ...props }) {
4
+ function useStableCallback(callback) {
5
+ const callbackRef = useRef(callback);
6
+ useEffect(() => {
7
+ callbackRef.current = callback;
8
+ }, [callback]);
9
+ return useCallback(() => {
10
+ callbackRef.current?.();
11
+ }, []);
12
+ }
13
+ export function Modal({ children, title, description, footer, width = 'default', onDismiss, ...props }) {
5
14
  const hasHeader = title != null || description != null;
6
- return (<SurfaceModal {...props}>
15
+ const stableOnDismiss = useStableCallback(onDismiss);
16
+ return (<SurfaceModal {...props} onDismiss={stableOnDismiss}>
7
17
  <Box maxWidth={resolveDialogWidth(width)} style={{ alignSelf: 'center', width: '100%' }}>
8
18
  <Stack gap="m">
9
19
  {hasHeader ? (<Stack gap="xs">
@@ -1 +1 @@
1
- {"version":3,"file":"Modal.js","sourceRoot":"","sources":["../../../src/components/modal/Modal.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,IAAI,YAAY,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AACtF,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAG5D,MAAM,UAAU,KAAK,CAAC,EACpB,QAAQ,EACR,KAAK,EACL,WAAW,EACX,MAAM,EACN,KAAK,GAAG,SAAS,EACjB,GAAG,KAAK,EACG;IACX,MAAM,SAAS,GAAG,KAAK,IAAI,IAAI,IAAI,WAAW,IAAI,IAAI,CAAC;IAEvD,OAAO,CACL,CAAC,YAAY,CAAC,IAAI,KAAK,CAAC,CACtB;MAAA,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CACtF;QAAA,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CACZ;UAAA,CAAC,SAAS,CAAC,CAAC,CAAC,CACX,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CACb;cAAA,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CACpD;cAAA,CAAC,WAAW,CAAC,CAAC,CAAC,CACb,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,CACpC;kBAAA,CAAC,WAAW,CACd;gBAAA,EAAE,IAAI,CAAC,CACR,CAAC,CAAC,CAAC,IAAI,CACV;YAAA,EAAE,KAAK,CAAC,CACT,CAAC,CAAC,CAAC,IAAI,CACR;UAAA,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CACxC;UAAA,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAC9C;QAAA,EAAE,KAAK,CACT;MAAA,EAAE,GAAG,CACP;IAAA,EAAE,YAAY,CAAC,CAChB,CAAC;AACJ,CAAC","sourcesContent":["import { Box, Heading, Modal as SurfaceModal, Stack, Text } from '@ankhorage/surface';\nimport React from 'react';\n\nimport { resolveDialogWidth } from '../../internal/recipes';\nimport type { ModalProps } from './types';\n\nexport function Modal({\n children,\n title,\n description,\n footer,\n width = 'default',\n ...props\n}: ModalProps) {\n const hasHeader = title != null || description != null;\n\n return (\n <SurfaceModal {...props}>\n <Box maxWidth={resolveDialogWidth(width)} style={{ alignSelf: 'center', width: '100%' }}>\n <Stack gap=\"m\">\n {hasHeader ? (\n <Stack gap=\"xs\">\n {title ? <Heading level={3}>{title}</Heading> : null}\n {description ? (\n <Text tone=\"muted\" variant=\"bodySmall\">\n {description}\n </Text>\n ) : null}\n </Stack>\n ) : null}\n {children ? <Box>{children}</Box> : null}\n {footer ? <Box pt=\"xs\">{footer}</Box> : null}\n </Stack>\n </Box>\n </SurfaceModal>\n );\n}\n"]}
1
+ {"version":3,"file":"Modal.js","sourceRoot":"","sources":["../../../src/components/modal/Modal.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,IAAI,YAAY,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AACtF,OAAO,KAAK,EAAE,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAE9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAG5D,SAAS,iBAAiB,CAAC,QAAkC;IAC3D,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;IAErC,SAAS,CAAC,GAAG,EAAE;QACb,WAAW,CAAC,OAAO,GAAG,QAAQ,CAAC;IACjC,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEf,OAAO,WAAW,CAAC,GAAG,EAAE;QACtB,WAAW,CAAC,OAAO,EAAE,EAAE,CAAC;IAC1B,CAAC,EAAE,EAAE,CAAC,CAAC;AACT,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,EACpB,QAAQ,EACR,KAAK,EACL,WAAW,EACX,MAAM,EACN,KAAK,GAAG,SAAS,EACjB,SAAS,EACT,GAAG,KAAK,EACG;IACX,MAAM,SAAS,GAAG,KAAK,IAAI,IAAI,IAAI,WAAW,IAAI,IAAI,CAAC;IACvD,MAAM,eAAe,GAAG,iBAAiB,CAAC,SAAS,CAAC,CAAC;IAErD,OAAO,CACL,CAAC,YAAY,CAAC,IAAI,KAAK,CAAC,CAAC,SAAS,CAAC,CAAC,eAAe,CAAC,CAClD;MAAA,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CACtF;QAAA,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CACZ;UAAA,CAAC,SAAS,CAAC,CAAC,CAAC,CACX,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CACb;cAAA,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CACpD;cAAA,CAAC,WAAW,CAAC,CAAC,CAAC,CACb,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,CACpC;kBAAA,CAAC,WAAW,CACd;gBAAA,EAAE,IAAI,CAAC,CACR,CAAC,CAAC,CAAC,IAAI,CACV;YAAA,EAAE,KAAK,CAAC,CACT,CAAC,CAAC,CAAC,IAAI,CACR;UAAA,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CACxC;UAAA,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAC9C;QAAA,EAAE,KAAK,CACT;MAAA,EAAE,GAAG,CACP;IAAA,EAAE,YAAY,CAAC,CAChB,CAAC;AACJ,CAAC","sourcesContent":["import { Box, Heading, Modal as SurfaceModal, Stack, Text } from '@ankhorage/surface';\nimport React, { useCallback, useEffect, useRef } from 'react';\n\nimport { resolveDialogWidth } from '../../internal/recipes';\nimport type { ModalProps } from './types';\n\nfunction useStableCallback(callback: (() => void) | undefined): (() => void) | undefined {\n const callbackRef = useRef(callback);\n\n useEffect(() => {\n callbackRef.current = callback;\n }, [callback]);\n\n return useCallback(() => {\n callbackRef.current?.();\n }, []);\n}\n\nexport function Modal({\n children,\n title,\n description,\n footer,\n width = 'default',\n onDismiss,\n ...props\n}: ModalProps) {\n const hasHeader = title != null || description != null;\n const stableOnDismiss = useStableCallback(onDismiss);\n\n return (\n <SurfaceModal {...props} onDismiss={stableOnDismiss}>\n <Box maxWidth={resolveDialogWidth(width)} style={{ alignSelf: 'center', width: '100%' }}>\n <Stack gap=\"m\">\n {hasHeader ? (\n <Stack gap=\"xs\">\n {title ? <Heading level={3}>{title}</Heading> : null}\n {description ? (\n <Text tone=\"muted\" variant=\"bodySmall\">\n {description}\n </Text>\n ) : null}\n </Stack>\n ) : null}\n {children ? <Box>{children}</Box> : null}\n {footer ? <Box pt=\"xs\">{footer}</Box> : null}\n </Stack>\n </Box>\n </SurfaceModal>\n );\n}\n"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ankhorage/zora",
3
3
  "type": "module",
4
- "version": "0.5.0",
4
+ "version": "0.5.1",
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": {
@@ -1,13 +1,26 @@
1
1
  import { Box, Drawer as SurfaceDrawer, Heading, Stack, Text } from '@ankhorage/surface';
2
- import React from 'react';
2
+ import React, { useCallback, useEffect, useRef } from 'react';
3
3
 
4
4
  import type { DrawerProps } from './types';
5
5
 
6
- export function Drawer({ children, title, description, footer, ...props }: DrawerProps) {
6
+ function useStableCallback(callback: (() => void) | undefined): (() => void) | undefined {
7
+ const callbackRef = useRef(callback);
8
+
9
+ useEffect(() => {
10
+ callbackRef.current = callback;
11
+ }, [callback]);
12
+
13
+ return useCallback(() => {
14
+ callbackRef.current?.();
15
+ }, []);
16
+ }
17
+
18
+ export function Drawer({ children, title, description, footer, onDismiss, ...props }: DrawerProps) {
7
19
  const hasHeader = title != null || description != null;
20
+ const stableOnDismiss = useStableCallback(onDismiss);
8
21
 
9
22
  return (
10
- <SurfaceDrawer {...props}>
23
+ <SurfaceDrawer {...props} onDismiss={stableOnDismiss}>
11
24
  <Stack gap="m">
12
25
  {hasHeader ? (
13
26
  <Stack gap="xs">
@@ -1,21 +1,35 @@
1
1
  import { Box, Heading, Modal as SurfaceModal, Stack, Text } from '@ankhorage/surface';
2
- import React from 'react';
2
+ import React, { useCallback, useEffect, useRef } from 'react';
3
3
 
4
4
  import { resolveDialogWidth } from '../../internal/recipes';
5
5
  import type { ModalProps } from './types';
6
6
 
7
+ function useStableCallback(callback: (() => void) | undefined): (() => void) | undefined {
8
+ const callbackRef = useRef(callback);
9
+
10
+ useEffect(() => {
11
+ callbackRef.current = callback;
12
+ }, [callback]);
13
+
14
+ return useCallback(() => {
15
+ callbackRef.current?.();
16
+ }, []);
17
+ }
18
+
7
19
  export function Modal({
8
20
  children,
9
21
  title,
10
22
  description,
11
23
  footer,
12
24
  width = 'default',
25
+ onDismiss,
13
26
  ...props
14
27
  }: ModalProps) {
15
28
  const hasHeader = title != null || description != null;
29
+ const stableOnDismiss = useStableCallback(onDismiss);
16
30
 
17
31
  return (
18
- <SurfaceModal {...props}>
32
+ <SurfaceModal {...props} onDismiss={stableOnDismiss}>
19
33
  <Box maxWidth={resolveDialogWidth(width)} style={{ alignSelf: 'center', width: '100%' }}>
20
34
  <Stack gap="m">
21
35
  {hasHeader ? (