@astryxdesign/cli 0.7.2-canary.fc12a18 → 0.7.2-canary.fdd384f
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/README.md +9 -8
- package/api/build/help/help.mjs +1 -1
- package/api/component/_adapter.d.mts +41 -1
- package/api/component/_adapter.mjs +93 -7
- package/api/component/component.mjs +22 -5
- package/api/component/component.test.mjs +420 -167
- package/api/component/integration-export-name.test.mjs +644 -0
- package/api/component/list/list.mjs +42 -4
- package/api/docs/_adapter.d.mts +11 -0
- package/api/docs/_adapter.mjs +244 -1
- package/api/docs/integrationDocs.test.mjs +124 -0
- package/api/doctor/theme-checks.mjs +1 -1
- package/api/gap-report/gap-report.mjs +67 -4
- package/api/index.d.mts +2 -0
- package/api/index.mjs +2 -0
- package/api/init/run/run.mjs +2 -2
- package/api/integration/_adapter.d.mts +12 -0
- package/api/integration/_adapter.mjs +54 -0
- package/api/integration/add-contribution.component-names.test.mjs +66 -0
- package/api/integration/add-contribution.mjs +8 -4
- package/api/integration/add-contribution.test.mjs +4 -2
- package/api/integration/authoring-checks.mjs +11 -2
- package/api/integration/authoring-checks.test.mjs +39 -0
- package/api/integration/authoring-checks.type.d.mts +9 -0
- package/api/integration/authoring-checks.type.mjs +14 -1
- package/api/integration/check/check.d.mts +96 -0
- package/api/integration/check/check.mjs +357 -0
- package/api/integration/check/check.test.mjs +489 -0
- package/api/integration/integration-check.type.d.mts +118 -0
- package/api/integration/integration-check.type.mjs +84 -0
- package/api/integration/integrationCheck.doc.d.mts +10 -0
- package/api/integration/integrationCheck.doc.mjs +73 -0
- package/api/integration/integrationComponentConflicts.doc.mjs +36 -5
- package/api/integration/pack-check.mjs +61 -107
- package/api/integration/pack-check.test.mjs +359 -0
- package/api/integration/validate-integration.mjs +8 -0
- package/api/integration/validate-integration.test.mjs +11 -0
- package/api/integration/validate-integration.type.d.mts +8 -0
- package/api/integration/validate-integration.type.mjs +12 -1
- package/api/integration/validateIntegration.doc.mjs +17 -3
- package/api/search/search.d.mts +9 -0
- package/api/search/search.integration-check.test.mjs +24 -0
- package/api/search/search.mjs +108 -16
- package/api/search/search.test.mjs +36 -0
- package/api/swizzle/copy/copy.mjs +28 -14
- package/api/template/template.test.mjs +120 -3
- package/api/theme/build/build.family.test.mjs +64 -0
- package/api/theme/build/build.mjs +180 -24
- package/api/theme/themeBuild.doc.mjs +4 -4
- package/assets/codemods/transforms/next/__tests__/migrate-list-edge-compensation-to-edge.test.mjs +120 -0
- package/assets/codemods/transforms/next/index.mjs +11 -1
- package/assets/codemods/transforms/next/migrate-list-edge-compensation-to-edge.mjs +198 -0
- package/assets/docs/README.md +10 -0
- package/assets/docs/author-a-theme.doc.mjs +1 -1
- package/assets/docs/getting-started.doc.mjs +3 -3
- package/assets/docs/theme.doc.dense.mjs +1 -1
- package/assets/docs/theme.doc.mjs +1 -1
- package/assets/docs/theme.doc.zh.mjs +1 -1
- package/assets/docs/tree/add-a-component.doc.mjs +10 -0
- package/assets/docs/tree/block-template.doc.mjs +2 -2
- package/assets/docs/tree/check-the-props.doc.mjs +196 -0
- package/assets/docs/tree/check-your-docs.doc.mjs +44 -3
- package/assets/docs/tree/checks.doc.mjs +21 -13
- package/assets/docs/tree/component-family.doc.mjs +5 -1
- package/assets/docs/tree/component-imports.doc.mjs +8 -0
- package/assets/docs/tree/describe-the-component.doc.mjs +1 -1
- package/assets/docs/tree/links.doc.mjs +2 -2
- package/assets/docs/tree/page-template.doc.mjs +1 -1
- package/assets/docs/tree/quick-start.doc.mjs +1 -1
- package/assets/docs/tree/replace-a-core-template.doc.mjs +1 -1
- package/assets/docs/tree/single-component.doc.mjs +3 -2
- package/assets/docs/tree/troubleshooting.doc.mjs +9 -1
- package/assets/docs/tree/type-scale.doc.mjs +3 -3
- package/assets/docs/tree/versioning.doc.mjs +1 -0
- package/assets/docs/tree/write-the-template-file.doc.mjs +2 -1
- package/assets/docs/use-a-theme.doc.mjs +2 -2
- package/assets/docs/working-with-ai.doc.mjs +43 -4
- package/assets/templates/blocks/components/Drawer/DrawerForm.doc.mjs +24 -0
- package/assets/templates/blocks/components/Drawer/DrawerForm.tsx +62 -0
- package/assets/templates/blocks/components/Drawer/DrawerScrim.doc.mjs +22 -0
- package/assets/templates/blocks/components/Drawer/DrawerScrim.tsx +68 -0
- package/assets/templates/blocks/components/Drawer/DrawerShowcase.doc.mjs +22 -0
- package/assets/templates/blocks/components/Drawer/DrawerShowcase.tsx +41 -0
- package/assets/templates/blocks/components/Drawer/DrawerStart.doc.mjs +21 -0
- package/assets/templates/blocks/components/Drawer/DrawerStart.tsx +41 -0
- package/assets/templates/blocks/components/Drawer/DrawerWidths.doc.mjs +22 -0
- package/assets/templates/blocks/components/Drawer/DrawerWidths.tsx +54 -0
- package/assets/templates/blocks/components/DrawerHeader/DrawerHeaderShowcase.doc.mjs +15 -0
- package/assets/templates/blocks/components/DrawerHeader/DrawerHeaderShowcase.tsx +73 -0
- package/assets/templates/blocks/components/DrawerHeader/DrawerHeaderSubtitleEndContent.doc.mjs +22 -0
- package/assets/templates/blocks/components/DrawerHeader/DrawerHeaderSubtitleEndContent.tsx +49 -0
- package/assets/templates/blocks/components/DrawerHeader/DrawerHeaderWithCloseButton.doc.mjs +21 -0
- package/assets/templates/blocks/components/DrawerHeader/DrawerHeaderWithCloseButton.tsx +42 -0
- package/assets/templates/pages/detail-page/page.tsx +3 -3
- package/assets/templates/pages/table-inbox/page.tsx +10 -8
- package/assets/theme.template.ts +1 -1
- package/authoring/doctypes/base/type.ts +6 -0
- package/authoring/doctypes/component/component.doc.mjs +4 -4
- package/authoring/doctypes/component/type.ts +6 -3
- package/authoring/doctypes/template/integration-template.doc.d.mts +11 -0
- package/authoring/doctypes/template/integration-template.doc.mjs +49 -0
- package/authoring/doctypes/template/parse.d.mts +6 -2
- package/authoring/doctypes/template/parse.mjs +3 -1
- package/authoring/doctypes/template/template.doc.mjs +1 -1
- package/authoring/doctypes/template/type.ts +22 -0
- package/authoring/index.d.ts +1 -0
- package/authoring/integration/integration.doc.mjs +8 -1
- package/authoring/integration/parse.test.mjs +10 -0
- package/authoring/integration/schema.d.mts +2 -0
- package/authoring/integration/schema.mjs +1 -0
- package/authoring/integration/type.ts +4 -0
- package/clients/cli/commands/build-theme.batch-report.test.mjs +3 -1
- package/clients/cli/commands/build-theme.mjs +1 -1
- package/clients/cli/commands/build-theme.path-safety.test.mjs +224 -6
- package/clients/cli/commands/build-theme.registry.test.mjs +5 -2
- package/clients/cli/commands/doctor-integration-components.doc.mjs +15 -4
- package/clients/cli/commands/doctor-integration-validate.doc.mjs +11 -2
- package/clients/cli/commands/doctor-integration.test.mjs +837 -0
- package/clients/cli/commands/doctor.mjs +190 -0
- package/clients/cli/commands/integration-check.doc.mjs +85 -0
- package/clients/cli/commands/integration-check.test.mjs +267 -0
- package/clients/cli/commands/integration.doc.mjs +6 -2
- package/clients/cli/commands/integration.mjs +107 -1
- package/clients/cli/commands/text-json-parity.test.mjs +5 -0
- package/clients/cli/commands/theme-build.doc.mjs +2 -2
- package/clients/cli/index.mjs +1 -0
- package/clients/cli/lib/component-format.mjs +5 -1
- package/foundation/config/project.mjs +82 -0
- package/foundation/discovery/authoring-self-docs.mjs +1 -0
- package/foundation/discovery/component-discovery.d.mts +190 -10
- package/foundation/discovery/component-discovery.export-names.test.mjs +760 -0
- package/foundation/discovery/component-discovery.mjs +864 -56
- package/foundation/discovery/component-discovery.test.mjs +96 -0
- package/foundation/discovery/component-replacement.mjs +18 -0
- package/foundation/discovery/component-replacement.test.mjs +40 -0
- package/foundation/discovery/doc-types.d.mts +157 -0
- package/foundation/discovery/doc-types.mjs +1224 -0
- package/foundation/discovery/doc-types.test.mjs +652 -0
- package/foundation/discovery/docs-discovery.d.mts +81 -0
- package/foundation/discovery/docs-discovery.mjs +57 -0
- package/foundation/discovery/integration-doc-files.d.mts +22 -0
- package/foundation/discovery/integration-doc-files.mjs +231 -0
- package/foundation/discovery/integration-doc-files.test.mjs +246 -0
- package/foundation/discovery/module-exports.d.mts +27 -0
- package/foundation/discovery/module-exports.mjs +356 -31
- package/foundation/discovery/module-exports.test.mjs +172 -0
- package/foundation/discovery/package-tsconfig.d.mts +14 -0
- package/foundation/discovery/package-tsconfig.mjs +228 -0
- package/foundation/discovery/package-tsconfig.test.mjs +210 -0
- package/foundation/discovery/project-typescript.d.mts +23 -0
- package/foundation/discovery/project-typescript.mjs +61 -0
- package/foundation/discovery/prop-drift.d.mts +278 -0
- package/foundation/discovery/prop-drift.mjs +2263 -0
- package/foundation/discovery/prop-drift.test.mjs +2219 -0
- package/foundation/discovery/template-adapter.mjs +74 -5
- package/foundation/discovery/type-match.d.mts +53 -0
- package/foundation/discovery/type-match.mjs +660 -0
- package/foundation/discovery/type-match.test.mjs +169 -0
- package/foundation/discovery/type-text.d.mts +68 -0
- package/foundation/discovery/type-text.mjs +658 -0
- package/foundation/discovery/type-text.test.mjs +196 -0
- package/foundation/discovery/unresolved-references.d.mts +62 -0
- package/foundation/discovery/unresolved-references.mjs +790 -0
- package/foundation/discovery/unresolved-references.test.mjs +567 -0
- package/foundation/doc-compiler/doc-loads.test.mjs +11 -1
- package/foundation/doc-compiler/inputs.mjs +23 -0
- package/foundation/doc-compiler/inputs.test.mjs +0 -1
- package/foundation/doc-compiler/links.d.mts +9 -5
- package/foundation/doc-compiler/links.mjs +4 -2
- package/foundation/integrations/contribution-inventory.mjs +6 -1
- package/foundation/response/response-types.doc.mjs +7 -2
- package/foundation/xle/registry.mjs +4 -0
- package/foundation/xle/registry.test.mjs +28 -0
- package/package.json +10 -10
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
'use client';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @input Controlled open state for a modal Drawer
|
|
7
|
+
* @output A DrawerHeader with a subtitle, a status badge in its end slot, and a close button
|
|
8
|
+
* @position Copyable DrawerHeader example
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import {useState} from 'react';
|
|
12
|
+
import {Drawer, DrawerHeader} from '@astryxdesign/core/Drawer';
|
|
13
|
+
import {Badge} from '@astryxdesign/core/Badge';
|
|
14
|
+
import {Button} from '@astryxdesign/core/Button';
|
|
15
|
+
import {Layout, LayoutContent} from '@astryxdesign/core/Layout';
|
|
16
|
+
import {Text} from '@astryxdesign/core/Text';
|
|
17
|
+
|
|
18
|
+
export default function DrawerHeaderSubtitleEndContent() {
|
|
19
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<>
|
|
23
|
+
<Button label="Open host details" onClick={() => setIsOpen(true)} />
|
|
24
|
+
<Drawer
|
|
25
|
+
isOpen={isOpen}
|
|
26
|
+
onOpenChange={setIsOpen}
|
|
27
|
+
label="web-prod-04"
|
|
28
|
+
width={360}>
|
|
29
|
+
<Layout
|
|
30
|
+
header={
|
|
31
|
+
<DrawerHeader
|
|
32
|
+
title="web-prod-04"
|
|
33
|
+
subtitle="us-east-1"
|
|
34
|
+
endContent={<Badge label="Healthy" variant="success" />}
|
|
35
|
+
onOpenChange={setIsOpen}
|
|
36
|
+
/>
|
|
37
|
+
}
|
|
38
|
+
content={
|
|
39
|
+
<LayoutContent>
|
|
40
|
+
<Text type="body">
|
|
41
|
+
All 6 instances are passing readiness checks.
|
|
42
|
+
</Text>
|
|
43
|
+
</LayoutContent>
|
|
44
|
+
}
|
|
45
|
+
/>
|
|
46
|
+
</Drawer>
|
|
47
|
+
</>
|
|
48
|
+
);
|
|
49
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/** @type {import('@astryxdesign/cli/authoring').TemplateDoc} */
|
|
4
|
+
export const doc = {
|
|
5
|
+
type: 'block',
|
|
6
|
+
name: 'With close button',
|
|
7
|
+
displayName: 'With close button',
|
|
8
|
+
description:
|
|
9
|
+
'Pass onOpenChange to render a close button that calls it with false. Drawer renders no close button of its own, so this is the usual visible way to close.',
|
|
10
|
+
exampleFor: 'DrawerHeader',
|
|
11
|
+
isReady: true,
|
|
12
|
+
aspectRatio: 16 / 9,
|
|
13
|
+
componentsUsed: [
|
|
14
|
+
'Drawer',
|
|
15
|
+
'DrawerHeader',
|
|
16
|
+
'Button',
|
|
17
|
+
'Layout',
|
|
18
|
+
'LayoutContent',
|
|
19
|
+
'Text',
|
|
20
|
+
],
|
|
21
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
'use client';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @input Controlled open state for a modal Drawer
|
|
7
|
+
* @output A Drawer whose DrawerHeader renders a close button because it receives onOpenChange
|
|
8
|
+
* @position Copyable DrawerHeader example
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import {useState} from 'react';
|
|
12
|
+
import {Drawer, DrawerHeader} from '@astryxdesign/core/Drawer';
|
|
13
|
+
import {Button} from '@astryxdesign/core/Button';
|
|
14
|
+
import {Layout, LayoutContent} from '@astryxdesign/core/Layout';
|
|
15
|
+
import {Text} from '@astryxdesign/core/Text';
|
|
16
|
+
|
|
17
|
+
export default function DrawerHeaderWithCloseButton() {
|
|
18
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<>
|
|
22
|
+
<Button label="Open drawer" onClick={() => setIsOpen(true)} />
|
|
23
|
+
<Drawer
|
|
24
|
+
isOpen={isOpen}
|
|
25
|
+
onOpenChange={setIsOpen}
|
|
26
|
+
label="Details"
|
|
27
|
+
width={360}>
|
|
28
|
+
<Layout
|
|
29
|
+
header={<DrawerHeader title="Details" onOpenChange={setIsOpen} />}
|
|
30
|
+
content={
|
|
31
|
+
<LayoutContent>
|
|
32
|
+
<Text type="body">
|
|
33
|
+
Passing onOpenChange renders the close button, which calls it
|
|
34
|
+
with false.
|
|
35
|
+
</Text>
|
|
36
|
+
</LayoutContent>
|
|
37
|
+
}
|
|
38
|
+
/>
|
|
39
|
+
</Drawer>
|
|
40
|
+
</>
|
|
41
|
+
);
|
|
42
|
+
}
|
|
@@ -600,9 +600,9 @@ export default function DetailPage2Template() {
|
|
|
600
600
|
}
|
|
601
601
|
end={!isNarrow && showSidePanel ? <RightPanel /> : undefined}
|
|
602
602
|
/>
|
|
603
|
-
{/* Mobile: the side
|
|
604
|
-
|
|
605
|
-
|
|
603
|
+
{/* Mobile: the side-panel content uses the full viewport so order details
|
|
604
|
+
are not squeezed beside narrow page chrome. Drawer remains available
|
|
605
|
+
for side-overlay flows that intentionally preserve page context. */}
|
|
606
606
|
<Dialog
|
|
607
607
|
variant="fullscreen"
|
|
608
608
|
isOpen={isNarrow && isPanelDialogOpen}
|
|
@@ -1652,8 +1652,8 @@ const COMPOSER_TOOLS: {
|
|
|
1652
1652
|
/**
|
|
1653
1653
|
* The compose sheet.
|
|
1654
1654
|
*
|
|
1655
|
-
* **`BottomSheet hasScrim={false}
|
|
1656
|
-
*
|
|
1655
|
+
* **`BottomSheet hasScrim={false}` keeps this bottom-edge composer non-modal.**
|
|
1656
|
+
* With the scrim off the sheet opens with `show()` rather than
|
|
1657
1657
|
* `showModal()`, so it never enters the top layer, never makes the page inert
|
|
1658
1658
|
* and never locks body scroll: the inbox behind it stays live. That matters
|
|
1659
1659
|
* more here than anywhere else in this template, because writing a message is
|
|
@@ -1661,12 +1661,14 @@ const COMPOSER_TOOLS: {
|
|
|
1661
1661
|
* actually said, copy an order number out of a thread. A modal composer
|
|
1662
1662
|
* answers that with "close me first".
|
|
1663
1663
|
*
|
|
1664
|
-
* The trade is
|
|
1665
|
-
* edge,
|
|
1666
|
-
*
|
|
1667
|
-
*
|
|
1668
|
-
*
|
|
1669
|
-
*
|
|
1664
|
+
* The trade is bottom-edge geometry, and it is worth naming. A non-modal
|
|
1665
|
+
* `Drawer` keeps page context live from an inline edge, but it is a full-height
|
|
1666
|
+
* side panel; this composer intentionally rises from the bottom. A sheet's
|
|
1667
|
+
* positioner is `inset-inline: 0` with `justify-content: center`, and there is
|
|
1668
|
+
* no anchor, side or width prop. So this cannot be docked to the inline-end
|
|
1669
|
+
* corner the way a `Dialog` can be. `Dialog` takes a static `position` and would
|
|
1670
|
+
* put the window in that corner — but `Dialog` is always modal, so buying the
|
|
1671
|
+
* corner costs the live inbox.
|
|
1670
1672
|
* `ChatComposerDrawer` is a false friend: despite the name it is an in-flow
|
|
1671
1673
|
* disclosure tray for a ChatComposer's attachments, with no positioning of its
|
|
1672
1674
|
* own.
|
package/assets/theme.template.ts
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
*
|
|
19
19
|
* 1. WRAP THE APP. A theme does nothing until it is provided.
|
|
20
20
|
*
|
|
21
|
-
* import {Theme} from '@astryxdesign/core';
|
|
21
|
+
* import {Theme} from '@astryxdesign/core/theme';
|
|
22
22
|
* import {myTheme} from './theme';
|
|
23
23
|
*
|
|
24
24
|
* <Theme theme={myTheme} mode="system"> // 'system' | 'light' | 'dark'
|
|
@@ -383,6 +383,12 @@ export interface ComponentPropDoc {
|
|
|
383
383
|
* ```
|
|
384
384
|
*/
|
|
385
385
|
slotElements?: ComponentSlotElement[];
|
|
386
|
+
/** Lifecycle marker for a prop outside the stable compatibility promise
|
|
387
|
+
* (spec:AST-017 FR21). Set `'experimental'` on a stable component's
|
|
388
|
+
* optional `experimental` prop object, and say in `description` that its
|
|
389
|
+
* contents may change or be removed in a patch release. Omit for stable
|
|
390
|
+
* props. */
|
|
391
|
+
stability?: 'experimental';
|
|
386
392
|
}
|
|
387
393
|
|
|
388
394
|
/**
|
|
@@ -30,7 +30,7 @@ export const doc = {
|
|
|
30
30
|
name: 'name',
|
|
31
31
|
type: 'string',
|
|
32
32
|
description:
|
|
33
|
-
"Stable machine identity and directory name without the Astryx prefix, PascalCase. e.g. 'Button', 'TextInput', 'AppShell'. Change `displayName`, not `name`, to edit the visible label; registry URLs derive from this identity by default.",
|
|
33
|
+
"Stable machine identity and directory name without the Astryx prefix, PascalCase. e.g. 'Button', 'TextInput', 'AppShell'. For an integration component it is the export apps import: the doc sits beside the file that exports it, and when that file exports nothing under its own name, `name` may name the export it does have. Change `displayName`, not `name`, to edit the visible label; registry URLs derive from this identity by default.",
|
|
34
34
|
required: true,
|
|
35
35
|
},
|
|
36
36
|
{
|
|
@@ -56,7 +56,7 @@ export const doc = {
|
|
|
56
56
|
name: 'replaces',
|
|
57
57
|
type: 'string',
|
|
58
58
|
description:
|
|
59
|
-
|
|
59
|
+
'Integration components only: the exact `name` of the Core ComponentDoc this component takes over for unqualified lookup, so every app that loads the integration gets it from component detail, component lists, search, `swizzle <Name>`, and issue routing; `swizzle --list` keeps listing Core names. The Core original stays reachable with `--package @astryxdesign/core`. It takes effect only when the package\'s peer range starts at the release that applies it, `"@astryxdesign/cli": ">=0.6.7"` or later; without such a range the component keeps its own name and `doctor integration components` warns. Set it only to intentionally own a Core identity; give an alternative or variant its own name instead.',
|
|
60
60
|
},
|
|
61
61
|
{
|
|
62
62
|
name: 'keywords',
|
|
@@ -181,13 +181,13 @@ export const doc = {
|
|
|
181
181
|
name: 'props',
|
|
182
182
|
type: 'ComponentPropDoc[]',
|
|
183
183
|
description:
|
|
184
|
-
'SingleComponentDoc variant (required there): all public props for the one primary component. Each prop is {name, type, description, default?, required?, slotElements?}. Skip styling props like xstyle/className/style. Also present on SubComponentDoc.',
|
|
184
|
+
'SingleComponentDoc variant (required there): all public props for the one primary component. Each prop is {name, type, description, default?, required?, slotElements?, stability?}. Skip styling props like xstyle/className/style. Also present on SubComponentDoc.',
|
|
185
185
|
},
|
|
186
186
|
{
|
|
187
187
|
name: 'components',
|
|
188
188
|
type: '(ComponentEntry | ComponentRef)[]',
|
|
189
189
|
description:
|
|
190
|
-
'MultiComponentDoc variant (required there): one entry per public component/hook exported from the directory. Each entry is a full ComponentEntry (inline: name, displayName, description, props | params+returns) or a name-only ComponentRef pointing at a sibling {Name}.doc.mjs.',
|
|
190
|
+
'MultiComponentDoc variant (required there): one entry per public component/hook exported from the directory. Each entry is a full ComponentEntry (inline: name, displayName, description, props | params+returns) or a name-only ComponentRef pointing at a sibling {Name}.doc.mjs. In an integration, each full entry the module named by `import` exports is a component under its own name.',
|
|
191
191
|
},
|
|
192
192
|
{
|
|
193
193
|
name: 'subComponentOf',
|
|
@@ -33,9 +33,12 @@ export interface ComponentBaseDoc extends AuthoredDocGraphFields {
|
|
|
33
33
|
type?: 'component';
|
|
34
34
|
/**
|
|
35
35
|
* Stable machine identity and directory name without the Astryx prefix,
|
|
36
|
-
* PascalCase (for example `Button`, `Table`, or `AppShell`).
|
|
37
|
-
*
|
|
38
|
-
*
|
|
36
|
+
* PascalCase (for example `Button`, `Table`, or `AppShell`). For an
|
|
37
|
+
* integration component it is the export apps import: the doc sits beside
|
|
38
|
+
* the file that exports it, and when that file exports nothing under its own
|
|
39
|
+
* name, `name` may name the export it does have. Do not change this to edit
|
|
40
|
+
* the visible label; use `displayName` for that. Registry URLs derive from
|
|
41
|
+
* this value by default.
|
|
39
42
|
*/
|
|
40
43
|
name: string;
|
|
41
44
|
/** Human-readable display name with spaces between words, used by the
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// @generated by scripts/sync-api-types.mjs from the JSDoc in authoring/**/*.mjs.
|
|
2
|
+
// DO NOT EDIT — run `pnpm sync:api-types` to regenerate.
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @file SchemaDoc for the `IntegrationTemplateDoc` doc-type — the template
|
|
6
|
+
* metadata an integration package ships: TemplateDoc, with the package's own
|
|
7
|
+
* `category`. Colocated with the type it describes (`type.ts`).
|
|
8
|
+
* @position packages/cli/authoring/doctypes/template — doc-type documentation
|
|
9
|
+
*/
|
|
10
|
+
/** @type {import('@astryxdesign/cli/authoring').SchemaDoc} */
|
|
11
|
+
export const doc: import("@astryxdesign/cli/authoring").SchemaDoc;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file SchemaDoc for the `IntegrationTemplateDoc` doc-type — the template
|
|
5
|
+
* metadata an integration package ships: TemplateDoc, with the package's own
|
|
6
|
+
* `category`. Colocated with the type it describes (`type.ts`).
|
|
7
|
+
* @position packages/cli/authoring/doctypes/template — doc-type documentation
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/** @type {import('@astryxdesign/cli/authoring').SchemaDoc} */
|
|
11
|
+
export const doc = {
|
|
12
|
+
type: 'schema',
|
|
13
|
+
name: 'integration-template-doc',
|
|
14
|
+
displayName: 'IntegrationTemplateDoc',
|
|
15
|
+
namespace: 'authoring',
|
|
16
|
+
description:
|
|
17
|
+
"The doc-type for an integration package's template metadata. It has every " +
|
|
18
|
+
"TemplateDoc field and rule, except that `category` is the package's own " +
|
|
19
|
+
'string instead of a TemplateCategory value.',
|
|
20
|
+
appliesTo: '<Name>.doc.mjs',
|
|
21
|
+
fields: [
|
|
22
|
+
{
|
|
23
|
+
name: 'category',
|
|
24
|
+
type: 'string',
|
|
25
|
+
description:
|
|
26
|
+
"The package's own category. Bare `astryx template` groups the package's templates by it.",
|
|
27
|
+
},
|
|
28
|
+
],
|
|
29
|
+
examples: [
|
|
30
|
+
{
|
|
31
|
+
label: 'Block template in an integration package',
|
|
32
|
+
code: `/** @type {import('@astryxdesign/cli/authoring').IntegrationTemplateDoc} */
|
|
33
|
+
export default {
|
|
34
|
+
type: 'block',
|
|
35
|
+
name: 'acme-pricing-table',
|
|
36
|
+
displayName: 'Pricing Table',
|
|
37
|
+
description: 'Plans side by side, with the chosen plan highlighted.',
|
|
38
|
+
aspectRatio: 16 / 9,
|
|
39
|
+
category: 'Acme - Commerce',
|
|
40
|
+
};`,
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
notes: [
|
|
44
|
+
{
|
|
45
|
+
type: 'prose',
|
|
46
|
+
text: "Every other field, and the page and block variants, are TemplateDoc's. Core's own templates use TemplateDoc, whose `category` is a TemplateCategory value. `astryx doctor integration validate` checks an integration's template docs against IntegrationTemplateDoc.",
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
};
|
|
@@ -18,7 +18,9 @@ export type BlockTemplateDoc = import("./type.js").BlockTemplateDoc;
|
|
|
18
18
|
* Templates as they load. Integration templates already published omit
|
|
19
19
|
* `displayName` and `aspectRatio` and group themselves under their own
|
|
20
20
|
* `category`, so the loader accepts those (template discovery falls back to an
|
|
21
|
-
* aspect ratio of 1). The published
|
|
21
|
+
* aspect ratio of 1). The published `TemplateDoc` keeps asking authors for all
|
|
22
|
+
* three; `IntegrationTemplateDoc`, for an integration package's templates,
|
|
23
|
+
* takes the package's own `category`.
|
|
22
24
|
*/
|
|
23
25
|
export type LoadedPageTemplateDoc = Omit<PageTemplateDoc, "displayName" | "category"> & {
|
|
24
26
|
displayName?: string;
|
|
@@ -28,7 +30,9 @@ export type LoadedPageTemplateDoc = Omit<PageTemplateDoc, "displayName" | "categ
|
|
|
28
30
|
* Templates as they load. Integration templates already published omit
|
|
29
31
|
* `displayName` and `aspectRatio` and group themselves under their own
|
|
30
32
|
* `category`, so the loader accepts those (template discovery falls back to an
|
|
31
|
-
* aspect ratio of 1). The published
|
|
33
|
+
* aspect ratio of 1). The published `TemplateDoc` keeps asking authors for all
|
|
34
|
+
* three; `IntegrationTemplateDoc`, for an integration package's templates,
|
|
35
|
+
* takes the package's own `category`.
|
|
32
36
|
*/
|
|
33
37
|
export type LoadedBlockTemplateDoc = Omit<BlockTemplateDoc, "displayName" | "aspectRatio" | "category"> & {
|
|
34
38
|
displayName?: string;
|
|
@@ -78,7 +78,9 @@ const blockTemplateSchema = z
|
|
|
78
78
|
* Templates as they load. Integration templates already published omit
|
|
79
79
|
* `displayName` and `aspectRatio` and group themselves under their own
|
|
80
80
|
* `category`, so the loader accepts those (template discovery falls back to an
|
|
81
|
-
* aspect ratio of 1). The published
|
|
81
|
+
* aspect ratio of 1). The published `TemplateDoc` keeps asking authors for all
|
|
82
|
+
* three; `IntegrationTemplateDoc`, for an integration package's templates,
|
|
83
|
+
* takes the package's own `category`.
|
|
82
84
|
*
|
|
83
85
|
* @typedef {Omit<PageTemplateDoc, 'displayName' | 'category'>
|
|
84
86
|
* & {displayName?: string, category?: string}} LoadedPageTemplateDoc
|
|
@@ -162,7 +162,7 @@ export default {
|
|
|
162
162
|
notes: [
|
|
163
163
|
{
|
|
164
164
|
type: 'prose',
|
|
165
|
-
text: 'When it loads, a template may leave out `displayName` and `aspectRatio` and use its own `category`, as integration templates already published do; a block with no `aspectRatio` previews at 1. Write to the type anyway; it is the contract
|
|
165
|
+
text: 'When it loads, a template may leave out `displayName` and `aspectRatio` and use its own `category`, as integration templates already published do; a block with no `aspectRatio` previews at 1. Write to the type anyway; it is the contract, and `astryx doctor integration validate` warns about an integration template that leaves out `displayName` or `aspectRatio`.',
|
|
166
166
|
},
|
|
167
167
|
{
|
|
168
168
|
type: 'prose',
|
|
@@ -201,3 +201,25 @@ export type TemplateCategory =
|
|
|
201
201
|
| 'Shell - Blank';
|
|
202
202
|
|
|
203
203
|
export type TemplateDoc = PageTemplateDoc | BlockTemplateDoc;
|
|
204
|
+
|
|
205
|
+
/** A page template an integration package ships, with its own `category`. */
|
|
206
|
+
export interface IntegrationPageTemplateDoc extends Omit<
|
|
207
|
+
PageTemplateDoc,
|
|
208
|
+
'category'
|
|
209
|
+
> {
|
|
210
|
+
category?: string;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/** A block template an integration package ships, with its own `category`. */
|
|
214
|
+
export interface IntegrationBlockTemplateDoc extends Omit<
|
|
215
|
+
BlockTemplateDoc,
|
|
216
|
+
'category'
|
|
217
|
+
> {
|
|
218
|
+
category?: string;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/** The doc-type for an integration package's template metadata: TemplateDoc,
|
|
222
|
+
* with `category` the package's own string (bare `astryx template` groups
|
|
223
|
+
* the package's templates by it) instead of a TemplateCategory value. */
|
|
224
|
+
export type IntegrationTemplateDoc =
|
|
225
|
+
IntegrationPageTemplateDoc | IntegrationBlockTemplateDoc;
|
package/authoring/index.d.ts
CHANGED
|
@@ -28,6 +28,7 @@ export type {HookDoc} from './doctypes/types.js'; // useToast.doc.mjs
|
|
|
28
28
|
export type {FunctionDoc} from './doctypes/types.js'; // search.doc.mjs (hook | api)
|
|
29
29
|
export type {ReferenceDoc} from './doctypes/types.js'; // theming.doc.mjs
|
|
30
30
|
export type {TemplateDoc} from './doctypes/types.js'; // Foo.doc.mjs
|
|
31
|
+
export type {IntegrationTemplateDoc} from './doctypes/types.js'; // an integration's Foo.doc.mjs
|
|
31
32
|
export type {SchemaDoc} from './doctypes/types.js'; // config.doc.mjs (object shape)
|
|
32
33
|
export type {CommandDoc} from './doctypes/types.js'; // search.doc.mjs (CLI command)
|
|
33
34
|
export type {EnumDoc} from './doctypes/types.js'; // error-codes.doc.mjs (vocabulary)
|
|
@@ -74,6 +74,13 @@ export const doc = {
|
|
|
74
74
|
description: 'Where to file issues/feedback for this integration.',
|
|
75
75
|
example: "'https://github.com/acme/widgets/issues'",
|
|
76
76
|
},
|
|
77
|
+
{
|
|
78
|
+
name: 'docsiteUrl',
|
|
79
|
+
type: 'string',
|
|
80
|
+
description:
|
|
81
|
+
"Link to this integration's docs site, such as its home page. Catalogs that list the package may show it.",
|
|
82
|
+
example: "'https://widgets.acme.dev'",
|
|
83
|
+
},
|
|
77
84
|
],
|
|
78
85
|
examples: [
|
|
79
86
|
{
|
|
@@ -118,7 +125,7 @@ export const doc = {
|
|
|
118
125
|
text:
|
|
119
126
|
'Validate the manifest with `astryx doctor integration validate`. At the ' +
|
|
120
127
|
'load boundary, a known field of the wrong type is an error, issuesUrl ' +
|
|
121
|
-
'must be
|
|
128
|
+
'and docsiteUrl must be valid URLs, and unknown fields become warnings so an older CLI ' +
|
|
122
129
|
'can still load the fields it understands. Before publishing, also run ' +
|
|
123
130
|
'`templates`, `components`, and `docs` under the same `doctor integration` ' +
|
|
124
131
|
'group. Those leaves compare authored identities with Core and explain ' +
|
|
@@ -87,6 +87,16 @@ describe('parseIntegration (load boundary)', () => {
|
|
|
87
87
|
expect(reason({issuesUrl: 'nope'})).toContain('issuesUrl');
|
|
88
88
|
});
|
|
89
89
|
|
|
90
|
+
it('accepts a docsiteUrl as a known key', () => {
|
|
91
|
+
const manifest = {docsiteUrl: 'https://widgets.example.com'};
|
|
92
|
+
expect(parseIntegration(manifest)).toEqual(manifest);
|
|
93
|
+
expect(unknownIntegrationKeys(manifest)).toEqual([]);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it('rejects a non-URL docsiteUrl', () => {
|
|
97
|
+
expect(reason({docsiteUrl: 'nope'})).toContain('docsiteUrl');
|
|
98
|
+
});
|
|
99
|
+
|
|
90
100
|
it('rejects a noncanonical providerId', () => {
|
|
91
101
|
expect(reason({providerId: 'Acme Widgets'})).toContain('providerId');
|
|
92
102
|
});
|
|
@@ -39,6 +39,7 @@ export const integrationBaseSchema: z.ZodObject<{
|
|
|
39
39
|
docs: z.ZodOptional<z.ZodString>;
|
|
40
40
|
themes: z.ZodOptional<z.ZodString>;
|
|
41
41
|
issuesUrl: z.ZodOptional<z.ZodString>;
|
|
42
|
+
docsiteUrl: z.ZodOptional<z.ZodString>;
|
|
42
43
|
}, z.core.$strip>;
|
|
43
44
|
export const integrationSchema: z.ZodObject<{
|
|
44
45
|
providerId: z.ZodOptional<z.ZodString>;
|
|
@@ -48,6 +49,7 @@ export const integrationSchema: z.ZodObject<{
|
|
|
48
49
|
docs: z.ZodOptional<z.ZodString>;
|
|
49
50
|
themes: z.ZodOptional<z.ZodString>;
|
|
50
51
|
issuesUrl: z.ZodOptional<z.ZodString>;
|
|
52
|
+
docsiteUrl: z.ZodOptional<z.ZodString>;
|
|
51
53
|
agentDocs: z.ZodOptional<z.ZodObject<{
|
|
52
54
|
append: z.ZodOptional<z.ZodReadonly<z.ZodArray<z.ZodString>>>;
|
|
53
55
|
}, z.core.$strip>>;
|
|
@@ -78,6 +78,7 @@ export const integrationBaseSchema = z.object({
|
|
|
78
78
|
docs: z.string().optional(),
|
|
79
79
|
themes: z.string().optional(),
|
|
80
80
|
issuesUrl: z.string().url().optional(),
|
|
81
|
+
docsiteUrl: z.string().url().optional(),
|
|
81
82
|
});
|
|
82
83
|
|
|
83
84
|
// Unknown top-level keys are stripped rather than rejected. `.strict()` made a key from a
|
|
@@ -44,6 +44,10 @@ export interface AstryxIntegration {
|
|
|
44
44
|
};
|
|
45
45
|
/** Where to file issues/feedback for this integration. */
|
|
46
46
|
issuesUrl?: string;
|
|
47
|
+
/** Link to this integration's docs site, such as its home page. The CLI
|
|
48
|
+
* accepts it as a known field; catalogs that list the package may show
|
|
49
|
+
* it. */
|
|
50
|
+
docsiteUrl?: string;
|
|
47
51
|
}
|
|
48
52
|
|
|
49
53
|
/**
|
|
@@ -168,7 +168,9 @@ describe('theme build report', () => {
|
|
|
168
168
|
}
|
|
169
169
|
expect(count(out, 'Install in your app')).toBe(1);
|
|
170
170
|
expect(count(out, 'Or with a <link> tag:')).toBe(1);
|
|
171
|
-
expect(
|
|
171
|
+
expect(
|
|
172
|
+
count(out, "import { Theme } from '@astryxdesign/core/theme';"),
|
|
173
|
+
).toBe(2);
|
|
172
174
|
expect(count(out, '[note]')).toBe(1);
|
|
173
175
|
expect(count(out, 'note: Font')).toBe(0);
|
|
174
176
|
expect(count(out, 'fonts.googleapis.com/css2')).toBe(1);
|
|
@@ -397,7 +397,7 @@ function printThemeApp(result) {
|
|
|
397
397
|
emit(
|
|
398
398
|
text('Wire the generated module once in the app root:'),
|
|
399
399
|
code(
|
|
400
|
-
"import {Theme} from '@astryxdesign/core';\n" +
|
|
400
|
+
"import {Theme} from '@astryxdesign/core/theme';\n" +
|
|
401
401
|
`import {themes, defaultThemeSlug} from './${stem}';\n\n` +
|
|
402
402
|
'<Theme theme={themes[defaultThemeSlug]}>\n <App />\n</Theme>',
|
|
403
403
|
),
|