@ankhorage/zora 3.3.1 → 3.3.3
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/dist/components/card/meta.d.ts +1 -1
- package/dist/foundation/meta.d.ts +4 -4
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/layout/screen/meta.d.ts +1 -1
- package/dist/layout/screen-section/meta.d.ts +1 -1
- package/dist/metadata/allowedChildren.d.ts +4 -4
- package/dist/metadata/allowedChildren.d.ts.map +1 -1
- package/dist/metadata/allowedChildren.js +2 -0
- package/dist/metadata/allowedChildren.js.map +1 -1
- package/dist/metadata/bindableComponentMeta.d.ts +2 -2
- package/dist/metadata/componentMeta.d.ts.map +1 -1
- package/dist/metadata/componentMeta.js +2 -0
- package/dist/metadata/componentMeta.js.map +1 -1
- package/dist/metadata/index.d.ts +1 -1
- package/dist/metadata/index.d.ts.map +1 -1
- package/dist/metadata/index.js.map +1 -1
- package/dist/metadata/types.d.ts +6 -0
- package/dist/metadata/types.d.ts.map +1 -1
- package/dist/metadata/types.js.map +1 -1
- package/dist/patterns/content-rail/meta.d.ts +2 -2
- package/dist/patterns/message-bubble/meta.d.ts +1 -1
- package/dist/patterns/missing-element/MissingElement.d.ts +10 -0
- package/dist/patterns/missing-element/MissingElement.d.ts.map +1 -0
- package/dist/patterns/missing-element/MissingElement.js +41 -0
- package/dist/patterns/missing-element/MissingElement.js.map +1 -0
- package/dist/patterns/missing-element/index.d.ts +3 -0
- package/dist/patterns/missing-element/index.d.ts.map +1 -0
- package/dist/patterns/missing-element/index.js +2 -0
- package/dist/patterns/missing-element/index.js.map +1 -0
- package/dist/patterns/missing-element/meta.d.ts +68 -0
- package/dist/patterns/missing-element/meta.d.ts.map +1 -0
- package/dist/patterns/missing-element/meta.js +59 -0
- package/dist/patterns/missing-element/meta.js.map +1 -0
- package/dist/patterns/missing-element/types.d.ts +9 -0
- package/dist/patterns/missing-element/types.d.ts.map +1 -0
- package/dist/patterns/missing-element/types.js +2 -0
- package/dist/patterns/missing-element/types.js.map +1 -0
- package/dist/patterns/notice/meta.d.ts +1 -1
- package/dist/patterns/panel/meta.d.ts +1 -1
- package/dist/patterns/post-card/meta.d.ts +1 -1
- package/dist/patterns/reader/meta.d.ts +2 -2
- package/dist/patterns/scanner/meta.d.ts +2 -2
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +2 -0
- package/dist/registry.js.map +1 -1
- package/package.json +5 -5
- package/src/expo57Migration.test.ts +16 -1
- package/src/index.ts +3 -0
- package/src/metadata/allowedChildren.ts +2 -0
- package/src/metadata/componentMeta.test.ts +16 -0
- package/src/metadata/componentMeta.ts +2 -0
- package/src/metadata/index.ts +1 -0
- package/src/metadata/types.ts +7 -0
- package/src/patterns/missing-element/MissingElement.test.ts +66 -0
- package/src/patterns/missing-element/MissingElement.tsx +73 -0
- package/src/patterns/missing-element/index.ts +2 -0
- package/src/patterns/missing-element/meta.ts +62 -0
- package/src/patterns/missing-element/types.ts +9 -0
- package/src/patterns/theme-composer/ThemeComposer.test.ts +9 -13
- package/src/registry.ts +2 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { describe, expect, test } from 'bun:test';
|
|
2
|
+
|
|
3
|
+
import { ZORA_BINDABLE_COMPONENT_META, ZORA_COMPONENT_META } from '../../metadata';
|
|
4
|
+
import { missingElementMeta } from './meta';
|
|
5
|
+
|
|
6
|
+
describe('MissingElement draft contract', () => {
|
|
7
|
+
test('is a release-blocking manifest leaf distinct from completed states', () => {
|
|
8
|
+
expect(ZORA_COMPONENT_META.MissingElement).toBe(missingElementMeta);
|
|
9
|
+
expect(missingElementMeta.directManifestNode).toBe(true);
|
|
10
|
+
expect(missingElementMeta.allowedChildren).toEqual([]);
|
|
11
|
+
expect(missingElementMeta.manifestPolicy).toEqual({
|
|
12
|
+
kind: 'unresolved-element',
|
|
13
|
+
availability: 'draft-only',
|
|
14
|
+
releaseGate: 'blocked',
|
|
15
|
+
});
|
|
16
|
+
expect(ZORA_COMPONENT_META.Notice.manifestPolicy).toBeUndefined();
|
|
17
|
+
expect(ZORA_COMPONENT_META.EmptyState.manifestPolicy).toBeUndefined();
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
test('captures only stable serializable gap and layout data', () => {
|
|
21
|
+
expect(Object.keys(missingElementMeta.props)).toEqual([
|
|
22
|
+
'requestedCapability',
|
|
23
|
+
'reason',
|
|
24
|
+
'evidenceId',
|
|
25
|
+
'minimumWidth',
|
|
26
|
+
'minimumHeight',
|
|
27
|
+
]);
|
|
28
|
+
expect(missingElementMeta.blueprint.defaultProps).toEqual({
|
|
29
|
+
requestedCapability: 'Unresolved interface capability',
|
|
30
|
+
reason: 'No matching ZORA element is available.',
|
|
31
|
+
minimumWidth: 240,
|
|
32
|
+
minimumHeight: 160,
|
|
33
|
+
});
|
|
34
|
+
expect(() => JSON.stringify(missingElementMeta)).not.toThrow();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test('has no event, data-binding, runtime-requirement, or fallback contract', () => {
|
|
38
|
+
expect(missingElementMeta.events).toBeUndefined();
|
|
39
|
+
expect(missingElementMeta.requirements).toBeUndefined();
|
|
40
|
+
expect(ZORA_BINDABLE_COMPONENT_META).not.toHaveProperty('MissingElement');
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test('visibly and accessibly identifies the gap while preserving its minimum dimensions', async () => {
|
|
44
|
+
const source = await Bun.file('src/patterns/missing-element/MissingElement.tsx').text();
|
|
45
|
+
|
|
46
|
+
expect(source).toContain('accessibilityLabel={accessibilityLabel}');
|
|
47
|
+
expect(source).toContain('accessibilityRole="text"');
|
|
48
|
+
expect(source).toContain('accessible');
|
|
49
|
+
expect(source).toContain('minHeight={minimumHeight}');
|
|
50
|
+
expect(source).toContain('minWidth={minimumWidth}');
|
|
51
|
+
expect(source).toContain('{requestedCapability}');
|
|
52
|
+
expect(source).toContain('{reason}');
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test('accepts the canonical interaction policy without owning interactive behavior', async () => {
|
|
56
|
+
const [source, types] = await Promise.all([
|
|
57
|
+
Bun.file('src/patterns/missing-element/MissingElement.tsx').text(),
|
|
58
|
+
Bun.file('src/patterns/missing-element/types.ts').text(),
|
|
59
|
+
]);
|
|
60
|
+
|
|
61
|
+
expect(types).toContain('MissingElementProps extends ZoraBaseProps');
|
|
62
|
+
expect(source).toContain('interactionPolicy: _interactionPolicy');
|
|
63
|
+
expect(source).not.toMatch(/onPress|onLongPress|onChange|onSubmit/);
|
|
64
|
+
expect(source).not.toMatch(/<Button|<IconButton|<Notice|<EmptyState/);
|
|
65
|
+
});
|
|
66
|
+
});
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { StyleSheet } from 'react-native';
|
|
3
|
+
|
|
4
|
+
import { Badge } from '../../components/badge';
|
|
5
|
+
import { Text } from '../../components/text';
|
|
6
|
+
import { Box, Stack } from '../../foundation';
|
|
7
|
+
import { useZoraTheme } from '../../theme/useZoraTheme';
|
|
8
|
+
import { withZoraThemeScope } from '../../theme/withZoraThemeScope';
|
|
9
|
+
import type { MissingElementProps } from './types';
|
|
10
|
+
|
|
11
|
+
/***
|
|
12
|
+
* Renders the visible, non-interactive body of a draft missing-element marker.
|
|
13
|
+
*/
|
|
14
|
+
function MissingElementInner({
|
|
15
|
+
themeId: _themeId,
|
|
16
|
+
mode: _mode,
|
|
17
|
+
interactionPolicy: _interactionPolicy,
|
|
18
|
+
requestedCapability,
|
|
19
|
+
reason,
|
|
20
|
+
evidenceId,
|
|
21
|
+
minimumWidth,
|
|
22
|
+
minimumHeight,
|
|
23
|
+
testID,
|
|
24
|
+
}: MissingElementProps) {
|
|
25
|
+
const { theme } = useZoraTheme();
|
|
26
|
+
const accessibilityLabel = `Missing element: ${requestedCapability}. ${reason}`;
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<Box
|
|
30
|
+
accessibilityLabel={accessibilityLabel}
|
|
31
|
+
accessibilityRole="text"
|
|
32
|
+
accessible
|
|
33
|
+
bg={theme.semantics.warning.softBg}
|
|
34
|
+
borderColor={theme.semantics.warning.base}
|
|
35
|
+
borderWidth={1}
|
|
36
|
+
minHeight={minimumHeight}
|
|
37
|
+
minWidth={minimumWidth}
|
|
38
|
+
p="m"
|
|
39
|
+
radius="m"
|
|
40
|
+
style={styles.root}
|
|
41
|
+
testID={testID}
|
|
42
|
+
>
|
|
43
|
+
<Stack gap="xs">
|
|
44
|
+
<Badge color="warning">Missing element</Badge>
|
|
45
|
+
<Text variant="label" weight="semiBold">
|
|
46
|
+
{requestedCapability}
|
|
47
|
+
</Text>
|
|
48
|
+
<Text emphasis="muted" variant="bodySmall">
|
|
49
|
+
{reason}
|
|
50
|
+
</Text>
|
|
51
|
+
{evidenceId ? (
|
|
52
|
+
<Text emphasis="subtle" variant="caption">
|
|
53
|
+
Evidence: {evidenceId}
|
|
54
|
+
</Text>
|
|
55
|
+
) : null}
|
|
56
|
+
</Stack>
|
|
57
|
+
</Box>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const styles = StyleSheet.create({
|
|
62
|
+
root: {
|
|
63
|
+
borderStyle: 'dashed',
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
/***
|
|
68
|
+
* Draft-only marker that preserves an unsupported manifest region without faking its capability.
|
|
69
|
+
*
|
|
70
|
+
* `MissingElement` is intentionally non-interactive and release-blocking in component metadata.
|
|
71
|
+
* Replace it with a released semantic ZORA element before publishing a production template.
|
|
72
|
+
*/
|
|
73
|
+
export const MissingElement = withZoraThemeScope(MissingElementInner);
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { ZoraComponentMeta } from '../../metadata';
|
|
2
|
+
|
|
3
|
+
const instanceAuthoring = { authority: 'instance' } as const;
|
|
4
|
+
|
|
5
|
+
export const missingElementMeta = {
|
|
6
|
+
name: 'MissingElement',
|
|
7
|
+
category: 'pattern',
|
|
8
|
+
description:
|
|
9
|
+
'Draft-only marker for an unresolved semantic ZORA capability that must be replaced before release.',
|
|
10
|
+
directManifestNode: true,
|
|
11
|
+
allowedChildren: [],
|
|
12
|
+
manifestPolicy: {
|
|
13
|
+
kind: 'unresolved-element',
|
|
14
|
+
availability: 'draft-only',
|
|
15
|
+
releaseGate: 'blocked',
|
|
16
|
+
},
|
|
17
|
+
blueprint: {
|
|
18
|
+
label: 'Missing element',
|
|
19
|
+
defaultProps: {
|
|
20
|
+
requestedCapability: 'Unresolved interface capability',
|
|
21
|
+
reason: 'No matching ZORA element is available.',
|
|
22
|
+
minimumWidth: 240,
|
|
23
|
+
minimumHeight: 160,
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
props: {
|
|
27
|
+
requestedCapability: {
|
|
28
|
+
type: 'string',
|
|
29
|
+
category: 'Gap',
|
|
30
|
+
label: 'Requested capability',
|
|
31
|
+
default: 'Unresolved interface capability',
|
|
32
|
+
authoring: instanceAuthoring,
|
|
33
|
+
},
|
|
34
|
+
reason: {
|
|
35
|
+
type: 'string',
|
|
36
|
+
category: 'Gap',
|
|
37
|
+
label: 'Reason',
|
|
38
|
+
default: 'No matching ZORA element is available.',
|
|
39
|
+
authoring: instanceAuthoring,
|
|
40
|
+
},
|
|
41
|
+
evidenceId: {
|
|
42
|
+
type: 'string',
|
|
43
|
+
category: 'Evidence',
|
|
44
|
+
label: 'Evidence ID',
|
|
45
|
+
authoring: instanceAuthoring,
|
|
46
|
+
},
|
|
47
|
+
minimumWidth: {
|
|
48
|
+
type: 'number',
|
|
49
|
+
category: 'Layout',
|
|
50
|
+
label: 'Minimum width',
|
|
51
|
+
default: 240,
|
|
52
|
+
authoring: instanceAuthoring,
|
|
53
|
+
},
|
|
54
|
+
minimumHeight: {
|
|
55
|
+
type: 'number',
|
|
56
|
+
category: 'Layout',
|
|
57
|
+
label: 'Minimum height',
|
|
58
|
+
default: 160,
|
|
59
|
+
authoring: instanceAuthoring,
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
} as const satisfies ZoraComponentMeta;
|
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
|
|
3
|
+
import { parseHexColorOrThrow } from '@ankhorage/color-theory';
|
|
2
4
|
import { APP_CATEGORIES } from '@ankhorage/contracts';
|
|
3
5
|
import { describe, expect, test } from 'bun:test';
|
|
4
6
|
|
|
5
7
|
import { zoraDefaultTheme } from '../../theme/zoraDefaultTheme';
|
|
6
8
|
import type { ThemeComposerProps } from './types';
|
|
7
9
|
|
|
10
|
+
const themeComposerSource = readFileSync(new URL('./ThemeComposer.tsx', import.meta.url), 'utf8');
|
|
11
|
+
|
|
8
12
|
// ---------------------------------------------------------------------------
|
|
9
13
|
// ThemeComposerProps shape tests
|
|
10
14
|
// ---------------------------------------------------------------------------
|
|
@@ -56,20 +60,12 @@ describe('ThemeComposerProps', () => {
|
|
|
56
60
|
});
|
|
57
61
|
|
|
58
62
|
// ---------------------------------------------------------------------------
|
|
59
|
-
// COLOR_HARMONIES
|
|
63
|
+
// COLOR_HARMONIES ownership
|
|
60
64
|
// ---------------------------------------------------------------------------
|
|
61
65
|
|
|
62
|
-
describe('COLOR_HARMONIES
|
|
63
|
-
test('
|
|
64
|
-
|
|
65
|
-
'monochromatic',
|
|
66
|
-
'analogous',
|
|
67
|
-
'complementary',
|
|
68
|
-
'triadic',
|
|
69
|
-
'tetradic',
|
|
70
|
-
'splitComplementary',
|
|
71
|
-
] as const;
|
|
72
|
-
expect(COLOR_HARMONIES).toEqual(expected);
|
|
66
|
+
describe('COLOR_HARMONIES ownership for ThemeComposer', () => {
|
|
67
|
+
test('derives Select options from the canonical Color Theory catalog', () => {
|
|
68
|
+
expect(themeComposerSource).toContain('COLOR_HARMONIES.map');
|
|
73
69
|
});
|
|
74
70
|
});
|
|
75
71
|
|
package/src/registry.ts
CHANGED
|
@@ -82,6 +82,7 @@ import { ImageUploadField } from './patterns/image-upload-field';
|
|
|
82
82
|
import { InspectorField } from './patterns/inspector-field';
|
|
83
83
|
import { List, ListRow, ListSection } from './patterns/list';
|
|
84
84
|
import { MessageBubble } from './patterns/message-bubble';
|
|
85
|
+
import { MissingElement } from './patterns/missing-element';
|
|
85
86
|
import { Notice } from './patterns/notice';
|
|
86
87
|
import { Panel } from './patterns/panel';
|
|
87
88
|
import { PostCard } from './patterns/post-card';
|
|
@@ -219,6 +220,7 @@ const _ZORA_COMPONENT_REGISTRY = {
|
|
|
219
220
|
ListRow,
|
|
220
221
|
ListSection,
|
|
221
222
|
MessageBubble,
|
|
223
|
+
MissingElement,
|
|
222
224
|
Notice,
|
|
223
225
|
Panel,
|
|
224
226
|
PostCard,
|