@hjmds/design-contracts 1.26.0 → 1.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agreement.d.ts +1 -0
- package/dist/agreement.d.ts.map +1 -1
- package/dist/agreement.js +2 -1
- package/dist/agreement.js.map +1 -1
- package/dist/auth-screen.d.ts +1 -1
- package/dist/behaviors.d.ts +1 -1
- package/dist/calendar.d.ts +1 -0
- package/dist/calendar.d.ts.map +1 -1
- package/dist/calendar.js +4 -1
- package/dist/calendar.js.map +1 -1
- package/dist/catalog.d.ts +78 -30
- package/dist/catalog.d.ts.map +1 -1
- package/dist/catalog.js +10 -5
- package/dist/catalog.js.map +1 -1
- package/dist/chart.d.ts +2 -0
- package/dist/chart.d.ts.map +1 -1
- package/dist/chart.js +1 -1
- package/dist/chart.js.map +1 -1
- package/dist/component-definitions.d.ts +1 -0
- package/dist/component-definitions.d.ts.map +1 -1
- package/dist/component-definitions.js +1 -0
- package/dist/component-definitions.js.map +1 -1
- package/dist/component-recipes.d.ts +53 -6
- package/dist/component-recipes.d.ts.map +1 -1
- package/dist/component-recipes.js +64 -10
- package/dist/component-recipes.js.map +1 -1
- package/dist/data-table.d.ts +11 -0
- package/dist/data-table.d.ts.map +1 -1
- package/dist/data-table.js +5 -0
- package/dist/data-table.js.map +1 -1
- package/dist/description-list.d.ts +3 -0
- package/dist/description-list.d.ts.map +1 -1
- package/dist/description-list.js +5 -1
- package/dist/description-list.js.map +1 -1
- package/dist/design-profile-layout.d.ts +28 -0
- package/dist/design-profile-layout.d.ts.map +1 -1
- package/dist/design-profile-layout.js +27 -3
- package/dist/design-profile-layout.js.map +1 -1
- package/dist/design-profile.d.ts.map +1 -1
- package/dist/design-profile.js +40 -8
- package/dist/design-profile.js.map +1 -1
- package/dist/field-group.d.ts +13 -0
- package/dist/field-group.d.ts.map +1 -1
- package/dist/field-group.js +17 -2
- package/dist/field-group.js.map +1 -1
- package/dist/foundations.d.ts +24 -11
- package/dist/foundations.d.ts.map +1 -1
- package/dist/foundations.js +40 -7
- package/dist/foundations.js.map +1 -1
- package/dist/heading.d.ts +5 -5
- package/dist/image-choice.d.ts +23 -0
- package/dist/image-choice.d.ts.map +1 -0
- package/dist/image-choice.js +26 -0
- package/dist/image-choice.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/masonry.d.ts +8 -0
- package/dist/masonry.d.ts.map +1 -1
- package/dist/masonry.js +12 -1
- package/dist/masonry.js.map +1 -1
- package/dist/number-field.d.ts +2 -2
- package/dist/number-field.d.ts.map +1 -1
- package/dist/number-field.js +4 -2
- package/dist/number-field.js.map +1 -1
- package/dist/qr-code-recipe.d.ts +1 -0
- package/dist/qr-code-recipe.d.ts.map +1 -1
- package/dist/qr-code-recipe.js +3 -1
- package/dist/qr-code-recipe.js.map +1 -1
- package/dist/recipes.d.ts +1 -1
- package/dist/recipes.d.ts.map +1 -1
- package/dist/recipes.js +1 -1
- package/dist/recipes.js.map +1 -1
- package/dist/result.d.ts +9 -0
- package/dist/result.d.ts.map +1 -1
- package/dist/result.js +5 -0
- package/dist/result.js.map +1 -1
- package/dist/screen-patterns.d.ts +139 -2
- package/dist/screen-patterns.d.ts.map +1 -1
- package/dist/screen-patterns.js +140 -1
- package/dist/screen-patterns.js.map +1 -1
- package/dist/sheet.d.ts +15 -1
- package/dist/sheet.d.ts.map +1 -1
- package/dist/sheet.js +20 -1
- package/dist/sheet.js.map +1 -1
- package/dist/showcase.d.ts +27 -27
- package/dist/showcase.js +27 -27
- package/dist/showcase.js.map +1 -1
- package/dist/tag.d.ts +10 -2
- package/dist/tag.d.ts.map +1 -1
- package/dist/tag.js +3 -2
- package/dist/tag.js.map +1 -1
- package/dist/tags-input.d.ts +6 -0
- package/dist/tags-input.d.ts.map +1 -1
- package/dist/tags-input.js +3 -1
- package/dist/tags-input.js.map +1 -1
- package/dist/text-formats.d.ts +2 -2
- package/dist/top.d.ts +2 -2
- package/dist/transfer-list.d.ts +1 -1
- package/dist/transfer-list.d.ts.map +1 -1
- package/dist/transfer-list.js +2 -1
- package/dist/transfer-list.js.map +1 -1
- package/dist/upload-item.d.ts +1 -10
- package/dist/upload-item.d.ts.map +1 -1
- package/dist/upload-item.js +1 -2
- package/dist/upload-item.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/docs/activity-chip.md +4 -3
- package/docs/catalog-freeze.json +5 -2
- package/docs/chart.md +1 -1
- package/docs/consumer-policy.md +13 -6
- package/docs/description-list.md +4 -0
- package/docs/design-profile.md +28 -2
- package/docs/font-roles.md +1 -1
- package/docs/generated/component-maturity.md +5 -4
- package/docs/generated/renderer-evidence.json +92 -6
- package/docs/generated/renderer-evidence.md +5 -3
- package/docs/generated/showcase-manifest.json +49 -1
- package/docs/gravity-letters.md +7 -2
- package/docs/masonry.md +4 -2
- package/docs/screen-patterns.md +5 -2
- package/docs/showcase.md +7 -9
- package/docs/stable-promotion.md +13 -1
- package/docs/usage/README.md +40 -10
- package/docs/usage/SELECTION.md +30 -4
- package/docs/usage/STANDARD.md +11 -2
- package/docs/usage/components/account-switcher.md +98 -0
- package/docs/usage/components/activity-chip.md +4 -4
- package/docs/usage/components/badge.md +1 -1
- package/docs/usage/components/bezier-editor.md +99 -0
- package/docs/usage/components/bottom-cta.md +2 -1
- package/docs/usage/components/button.md +26 -12
- package/docs/usage/components/carousel.md +4 -4
- package/docs/usage/components/chart.md +1 -0
- package/docs/usage/components/chat-message.md +18 -12
- package/docs/usage/components/chat-screen.md +6 -3
- package/docs/usage/components/cohort-retention-table.md +83 -0
- package/docs/usage/components/collapsible.md +7 -2
- package/docs/usage/components/comment-thread-row.md +102 -0
- package/docs/usage/components/comment-thread-screen.md +27 -13
- package/docs/usage/components/composition-layout.md +1 -0
- package/docs/usage/components/context-menu.md +32 -15
- package/docs/usage/components/conversation-row.md +11 -4
- package/docs/usage/components/conversion-funnel.md +85 -0
- package/docs/usage/components/correlation-matrix.md +80 -0
- package/docs/usage/components/data-table.md +4 -0
- package/docs/usage/components/description-list.md +2 -1
- package/docs/usage/components/editor-screen.md +9 -5
- package/docs/usage/components/effect-surface.md +4 -2
- package/docs/usage/components/empty-state.md +2 -2
- package/docs/usage/components/event-attendance-card.md +104 -0
- package/docs/usage/components/expandable-search.md +105 -0
- package/docs/usage/components/file-picker.md +5 -0
- package/docs/usage/components/filter-recovery.md +97 -0
- package/docs/usage/components/follow-profile-card.md +100 -0
- package/docs/usage/components/heading.md +6 -2
- package/docs/usage/components/histogram-explorer.md +89 -0
- package/docs/usage/components/icon-button.md +18 -2
- package/docs/usage/components/icon-tile.md +12 -4
- package/docs/usage/components/image-choice-group.md +81 -0
- package/docs/usage/components/import-field-mapping.md +94 -0
- package/docs/usage/components/inline-edit.md +105 -0
- package/docs/usage/components/keyboard-avoidance-context.md +60 -0
- package/docs/usage/components/keyboard-avoiding.md +5 -1
- package/docs/usage/components/list-detail-screen.md +4 -4
- package/docs/usage/components/list.md +1 -1
- package/docs/usage/components/masonry.md +6 -7
- package/docs/usage/components/media-selection-screen.md +7 -5
- package/docs/usage/components/media-transport.md +104 -0
- package/docs/usage/components/message-composer.md +13 -3
- package/docs/usage/components/moderation-screen.md +5 -2
- package/docs/usage/components/notification-inbox-screen.md +3 -3
- package/docs/usage/components/notification-row.md +64 -8
- package/docs/usage/components/onboarding-screen.md +1 -1
- package/docs/usage/components/overview-screen.md +9 -3
- package/docs/usage/components/pagination.md +18 -3
- package/docs/usage/components/password-rules-field.md +90 -0
- package/docs/usage/components/permission-screen.md +1 -1
- package/docs/usage/components/photo-source-sheet.md +1 -1
- package/docs/usage/components/popover.md +6 -3
- package/docs/usage/components/pricing-choice.md +85 -0
- package/docs/usage/components/profile-summary.md +56 -8
- package/docs/usage/components/progress.md +3 -3
- package/docs/usage/components/qr-code.md +5 -9
- package/docs/usage/components/repeatable-field-group.md +92 -0
- package/docs/usage/components/reply-composer.md +83 -0
- package/docs/usage/components/reply-message.md +85 -0
- package/docs/usage/components/result.md +3 -3
- package/docs/usage/components/saved-items-screen.md +7 -5
- package/docs/usage/components/screen-layout.md +21 -10
- package/docs/usage/components/search-field.md +1 -1
- package/docs/usage/components/section.md +2 -2
- package/docs/usage/components/selection-action-bar.md +89 -0
- package/docs/usage/components/settings-screen.md +13 -11
- package/docs/usage/components/sheet.md +19 -7
- package/docs/usage/components/shortcut-recorder.md +77 -0
- package/docs/usage/components/split-action.md +94 -0
- package/docs/usage/components/streaming-answer.md +94 -0
- package/docs/usage/components/switch.md +6 -2
- package/docs/usage/components/table-column-settings.md +88 -0
- package/docs/usage/components/target-summary.md +79 -0
- package/docs/usage/components/text.md +11 -5
- package/docs/usage/components/toggle-feedback-button.md +94 -0
- package/docs/usage/components/top-bar.md +8 -12
- package/docs/usage/components/transfer-task.md +87 -0
- package/docs/usage/compositions/action-recovery-optimistic.md +18 -14
- package/docs/usage/compositions/action-recovery-save.md +18 -14
- package/docs/usage/compositions/action-recovery-undo.md +18 -14
- package/docs/usage/compositions/activity-status.md +1 -1
- package/docs/usage/compositions/adaptive-content.md +2 -1
- package/docs/usage/compositions/collection-detail.md +6 -5
- package/docs/usage/compositions/collection-editing.md +13 -6
- package/docs/usage/compositions/command-records.md +5 -4
- package/docs/usage/compositions/communication.md +7 -5
- package/docs/usage/compositions/compound-controls.md +7 -3
- package/docs/usage/compositions/content-transition-comparison.md +10 -5
- package/docs/usage/compositions/data-layouts.md +12 -16
- package/docs/usage/compositions/data-workflows.md +7 -4
- package/docs/usage/compositions/date-time-selection.md +5 -5
- package/docs/usage/compositions/design-profile-comparison.md +22 -6
- package/docs/usage/compositions/disclosure.md +14 -9
- package/docs/usage/compositions/document-resource.md +1 -1
- package/docs/usage/compositions/environment-matrix.md +16 -12
- package/docs/usage/compositions/expo-interactions.md +9 -8
- package/docs/usage/compositions/family-drawer.md +9 -5
- package/docs/usage/compositions/field-group.md +7 -3
- package/docs/usage/compositions/interaction-adapters.md +11 -9
- package/docs/usage/compositions/interaction-flow-apply.md +17 -15
- package/docs/usage/compositions/interaction-flow-search.md +11 -7
- package/docs/usage/compositions/live-list.md +12 -8
- package/docs/usage/compositions/navigation-bar-collection.md +8 -3
- package/docs/usage/compositions/optional-motion.md +2 -2
- package/docs/usage/compositions/paper-surface.md +11 -6
- package/docs/usage/compositions/purpose-input-comment.md +10 -4
- package/docs/usage/compositions/purpose-input-message.md +10 -4
- package/docs/usage/compositions/reference-first.md +4 -4
- package/docs/usage/compositions/reference-review.md +4 -4
- package/docs/usage/compositions/reference-settings.md +4 -4
- package/docs/usage/compositions/selection-motion.md +2 -1
- package/docs/usage/compositions/social-compositions.md +7 -6
- package/docs/usage/compositions/stea-event-ticket.md +2 -4
- package/docs/usage/compositions/stea-order-progress.md +19 -21
- package/docs/usage/compositions/stea-pixel-empty.md +26 -26
- package/docs/usage/compositions/task-controls.md +7 -2
- package/docs/usage/compositions/texture-comparison.md +5 -5
- package/docs/usage/compositions/toast-layout.md +7 -3
- package/docs/usage/compositions/toggle-feedback.md +1 -1
- package/docs/usage/compositions/visual-foundations.md +10 -5
- package/docs/usage/compositions/web-additions.md +5 -1
- package/docs/usage/screens/common-chat.md +5 -3
- package/docs/usage/screens/common-comments.md +14 -9
- package/docs/usage/screens/common-conversation-list.md +109 -0
- package/docs/usage/screens/common-inbox.md +5 -3
- package/docs/usage/screens/common-login.md +7 -4
- package/docs/usage/screens/common-profile.md +16 -12
- package/docs/usage/screens/common-saved.md +12 -8
- package/docs/usage/screens/common-search.md +16 -8
- package/docs/usage/screens/common-settings.md +12 -11
- package/docs/usage/screens/common-shell.md +12 -10
- package/docs/usage/screens/dashboard.md +59 -56
- package/docs/usage/screens/discovery-gallery.md +18 -9
- package/docs/usage/screens/flow-collection.md +10 -6
- package/docs/usage/screens/flow-editor.md +9 -6
- package/docs/usage/screens/flow-media.md +12 -7
- package/docs/usage/screens/flow-moderation.md +9 -3
- package/docs/usage/screens/flow-onboarding.md +13 -8
- package/docs/usage/screens/flow-permission.md +5 -3
- package/docs/usage/screens/landing.md +20 -14
- package/docs/usage/screens/mockup-studio.md +100 -88
- package/docs/usage/screens/notification-settings.md +9 -7
- package/docs/usage/screens/product-bento.md +22 -10
- package/docs/usage/screens/reference-comparison.md +2 -2
- package/docs/usage/tokens/font-roles.md +18 -2
- package/docs/usage/tokens/typography.md +22 -11
- package/package.json +7 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transfer-list.js","sourceRoot":"","sources":["../src/transfer-list.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ColorReference } from \"./color-references.js\";\nimport type {\n BehaviorContract,\n CheckboxState,\n CollectionKey,\n SelectItemDescriptor,\n} from \"./behaviors.js\";\nimport {\n getCheckboxNextState,\n reconcileCheckboxSelection,\n toggleCheckboxSelection,\n} from \"./selection-helpers.js\";\nimport { collectionItemContract, focusIndicatorContract } from \"./component-contracts.js\";\nimport { validateCollection } from \"./collection.js\";\nimport { control, radius, spacing, stroke } from \"./foundations.js\";\nimport { semanticColors } from \"./semantic-colors.js\";\n\n/**\n * `docs/transfer-list.md`: two lists sharing one item set, split by whether\n * each id is in `targetKeys`. This is the same shape CheckboxGroup already\n * commits to (`ReadonlySet<Id>`, no third \"which panel\" enum to keep in\n * sync with membership) — one source of truth instead of two arrays that can\n * drift apart when an item is moved.\n */\nexport type TransferListPanel = \"source\" | \"target\";\n\nexport type TransferListDescriptor<Id extends CollectionKey = CollectionKey> = Readonly<{\n items: readonly SelectItemDescriptor<Id>[];\n targetKeys: ReadonlySet<Id>;\n}>;\n\nexport type TransferListSelection<Id extends CollectionKey = CollectionKey> = Readonly<{\n source: ReadonlySet<Id>;\n target: ReadonlySet<Id>;\n}>;\n\nfunction withPanelSelection<Id extends CollectionKey>(\n selection: TransferListSelection<Id>,\n panel: TransferListPanel,\n next: ReadonlySet<Id>,\n): TransferListSelection<Id> {\n return panel === \"source\"\n ? { source: next, target: selection.target }\n : { source: selection.source, target: next };\n}\n\nfunction assertKnownIds<Id extends CollectionKey>(\n label: string,\n ids: ReadonlySet<Id>,\n knownIds: ReadonlySet<Id>,\n): void {\n for (const id of ids) {\n if (!knownIds.has(id)) {\n throw new RangeError(`TransferList ${label} references an unknown item id: ${id}`);\n }\n }\n}\n\n/** An item already sitting entirely inside one panel (including all-in-target\n * or all-in-source) is valid — nothing here requires either panel to be\n * non-empty, and a disabled item is valid in either panel even though it can\n * never be moved by the UI. */\nexport function validateTransferListDescriptor<Id extends CollectionKey>(\n descriptor: TransferListDescriptor<Id>,\n): void {\n validateCollection({ items: descriptor.items });\n const knownIds = new Set(descriptor.items.map((item) => item.id));\n assertKnownIds(\"targetKeys\", descriptor.targetKeys, knownIds);\n}\n\nexport type TransferListPanels<Id extends CollectionKey = CollectionKey> = Readonly<{\n source: readonly SelectItemDescriptor<Id>[];\n target: readonly SelectItemDescriptor<Id>[];\n}>;\n\n/** Splits by `targetKeys` membership, preserving each item's relative order from `items`. */\nexport function resolveTransferListPanels<Id extends CollectionKey>(\n descriptor: TransferListDescriptor<Id>,\n): TransferListPanels<Id> {\n validateTransferListDescriptor(descriptor);\n const source: SelectItemDescriptor<Id>[] = [];\n const target: SelectItemDescriptor<Id>[] = [];\n for (const item of descriptor.items) {\n (descriptor.targetKeys.has(item.id) ? target : source).push(item);\n }\n return { source, target };\n}\n\nexport function validateTransferListSelection<Id extends CollectionKey>(\n descriptor: TransferListDescriptor<Id>,\n selection: TransferListSelection<Id>,\n): void {\n const panels = resolveTransferListPanels(descriptor);\n assertKnownIds(\"selection.source\", selection.source, new Set(panels.source.map((i) => i.id)));\n assertKnownIds(\"selection.target\", selection.target, new Set(panels.target.map((i) => i.id)));\n}\n\n/** Toggles one row's checkbox within its own panel; the other panel's selection is untouched. */\nexport function toggleTransferListSelection<Id extends CollectionKey>(\n descriptor: TransferListDescriptor<Id>,\n selection: TransferListSelection<Id>,\n panel: TransferListPanel,\n id: Id,\n): TransferListSelection<Id> {\n const panels = resolveTransferListPanels(descriptor);\n const next = toggleCheckboxSelection(panels[panel], selection[panel], id);\n return withPanelSelection(selection, panel, next);\n}\n\n/**\n * Same tri-state `CheckboxState` `resolveDataTableSelectAllState` derives for\n * a table header — disabled rows excluded from both the denominator and the\n * count — generalized from \"all rows\" to \"this one panel's rows\".\n */\nexport function resolveTransferListSelectAllState<Id extends CollectionKey>(\n descriptor: TransferListDescriptor<Id>,\n selection: TransferListSelection<Id>,\n panel: TransferListPanel,\n): CheckboxState {\n const items = resolveTransferListPanels(descriptor)[panel];\n const selectable = items.filter((item) => !item.disabled);\n if (selectable.length === 0) return false;\n const selectedCount = selectable.filter((item) => selection[panel].has(item.id)).length;\n if (selectedCount === 0) return false;\n return selectedCount === selectable.length ? true : \"mixed\";\n}\n\n/** Mixed-defaults-to-checked, matching `getCheckboxNextState`'s existing convention. */\nexport function toggleTransferListSelectAll<Id extends CollectionKey>(\n descriptor: TransferListDescriptor<Id>,\n selection: TransferListSelection<Id>,\n panel: TransferListPanel,\n): TransferListSelection<Id> {\n const current = resolveTransferListSelectAllState(descriptor, selection, panel);\n const checkAll = getCheckboxNextState(current);\n const items = resolveTransferListPanels(descriptor)[panel];\n const next = checkAll\n ? new Set(items.filter((item) => !item.disabled).map((item) => item.id))\n : new Set<Id>();\n return withPanelSelection(selection, panel, next);\n}\n\nexport type TransferListMoveDirection = \"toTarget\" | \"toSource\";\n\nexport type TransferListMoveResult<Id extends CollectionKey = CollectionKey> = Readonly<{\n targetKeys: ReadonlySet<Id>;\n selection: TransferListSelection<Id>;\n /** In origin-panel order — the product formats the announcement string from this. */\n movedIds: readonly Id[];\n}>;\n\n/**\n * Moves every enabled, currently-selected id out of its origin panel.\n * Disabled ids are skipped rather than rejected (a disabled row can never\n * enter a selection through `toggleTransferListSelection`, but a product\n * could hand one to `defaultSelectedKeys`, and skipping mirrors\n * `toggleTreeCheckedSelection`'s disabled guard rather than throwing on it).\n * Moved ids are cleared from the origin panel's selection and deliberately\n * left unselected in the destination panel — a move commits a value, it does\n * not also commit a new pending selection the user did not make.\n */\nexport function moveTransferListSelection<Id extends CollectionKey>(\n descriptor: TransferListDescriptor<Id>,\n selection: TransferListSelection<Id>,\n direction: TransferListMoveDirection,\n): TransferListMoveResult<Id> {\n validateTransferListSelection(descriptor, selection);\n const fromPanel: TransferListPanel = direction === \"toTarget\" ? \"source\" : \"target\";\n const fromItems = resolveTransferListPanels(descriptor)[fromPanel];\n const movedIds = fromItems\n .filter((item) => !item.disabled && selection[fromPanel].has(item.id))\n .map((item) => item.id);\n\n if (movedIds.length === 0) {\n return { targetKeys: descriptor.targetKeys, selection, movedIds: [] };\n }\n\n const movedIdSet = new Set(movedIds);\n const targetKeys =\n direction === \"toTarget\"\n ? new Set([...descriptor.targetKeys, ...movedIds])\n : new Set([...descriptor.targetKeys].filter((id) => !movedIdSet.has(id)));\n\n const nextFromSelection = new Set(\n [...selection[fromPanel]].filter((id) => !movedIdSet.has(id)),\n );\n return {\n targetKeys,\n selection: withPanelSelection(selection, fromPanel, nextFromSelection),\n movedIds,\n };\n}\n\n/**\n * Where focus lands once the moved rows are gone from a panel: the item that\n * slid into the first removed row's position, so keyboard users keep moving\n * down the list without their focus jumping to the top or vanishing. `null`\n * means the panel is now empty — the renderer falls back to the panel's\n * empty-state message or the move button, never to the document body.\n */\nexport function resolveTransferListFocusAfterMove<Id extends CollectionKey>(\n remainingPanelItems: readonly SelectItemDescriptor<Id>[],\n removedIndex: number,\n): Id | null {\n if (remainingPanelItems.length === 0) return null;\n const clamped = Math.min(Math.max(removedIndex, 0), remainingPanelItems.length - 1);\n return remainingPanelItems[clamped]!.id;\n}\n\n/** Drops selected ids that left either panel (item removed from `items` entirely). */\nexport function reconcileTransferListSelection<Id extends CollectionKey>(\n descriptor: TransferListDescriptor<Id>,\n selection: TransferListSelection<Id>,\n): TransferListSelection<Id> {\n const panels = resolveTransferListPanels(descriptor);\n const source = reconcileCheckboxSelection(panels.source, selection.source);\n const target = reconcileCheckboxSelection(panels.target, selection.target);\n if (source === selection.source && target === selection.target) return selection;\n return { source, target };\n}\n\nexport const transferListRecipe = {\n slots: [\n \"root\",\n \"panel\",\n \"panelHeader\",\n \"panelTitle\",\n \"panelCount\",\n \"list\",\n \"item\",\n \"itemCheckbox\",\n \"emptyState\",\n \"moveControls\",\n \"moveButton\",\n ] as const,\n panel: {\n background: semanticColors.canvas,\n border: semanticColors.border.default,\n borderWidth: stroke.default,\n radius: \"md\" as const,\n },\n panelHeader: {\n minHeight: 44,\n paddingHorizontal: spacing.sm,\n title: { color: semanticColors.content.body, textVariant: \"body\" as const },\n count: { color: semanticColors.content.secondary, textVariant: \"label\" as const },\n },\n item: collectionItemContract,\n emptyState: { color: semanticColors.content.secondary, textVariant: \"label\" as const },\n moveControls: { gap: spacing.sm },\n moveButton: {\n minTarget: control.minTouchTarget,\n color: semanticColors.content.brand,\n disabledOpacity: 0.4,\n },\n states: { focus: focusIndicatorContract },\n} as const satisfies {\n slots: readonly [\n \"root\",\n \"panel\",\n \"panelHeader\",\n \"panelTitle\",\n \"panelCount\",\n \"list\",\n \"item\",\n \"itemCheckbox\",\n \"emptyState\",\n \"moveControls\",\n \"moveButton\",\n ];\n panel: { background: ColorReference; border: ColorReference; borderWidth: number; radius: keyof typeof radius };\n panelHeader: {\n minHeight: number;\n paddingHorizontal: number;\n title: { color: ColorReference; textVariant: \"body\" };\n count: { color: ColorReference; textVariant: \"label\" };\n };\n item: typeof collectionItemContract;\n emptyState: { color: ColorReference; textVariant: \"label\" };\n moveControls: { gap: number };\n moveButton: { minTarget: number; color: ColorReference; disabledOpacity: number };\n states: { focus: typeof focusIndicatorContract };\n};\n\nexport const transferListBehavior = {\n controlled: [\"targetKeys\", \"defaultTargetKeys\", \"onTargetKeysChange\"],\n inputs: [\"items\"],\n events: [\"onMove\"],\n stateAxes: {\n availability: [\"enabled\", \"disabled\"],\n value: [\"empty\", \"filled\", \"selected\", \"mixed\"],\n },\n web: {\n roles: [\"group\", \"listbox\", \"option\", \"checkbox\", \"button\"],\n keyboard: [\"Tab\", \"Space\", \"Enter\", \"ArrowUp\", \"ArrowDown\", \"Home\", \"End\"],\n focus: \"roving\",\n },\n native: {\n roles: [\"list\", \"checkbox\", \"button\"],\n states: [\"disabled\", \"selected\", \"checked\"],\n actions: [\"toggle\", \"toggleSelectAll\", \"moveSelection\", \"moveItem\"],\n },\n scenarios: [\n \"moving-is-reachable-entirely-by-keyboard-select-with-space-then-activate-the-move-button\",\n \"moving-a-single-focused-row-does-not-require-first-opening-multi-select\",\n \"focus-after-a-move-lands-on-the-item-that-slid-into-the-removed-rows-position\",\n \"focus-after-emptying-a-panel-falls-back-to-its-empty-state-never-lost-to-the-document\",\n \"every-move-emits-which-ids-moved-so-the-product-can-announce-a-formatted-sentence\",\n \"disabled-items-are-never-selectable-and-never-move\",\n \"moved-items-are-cleared-from-the-origin-panels-selection-and-left-unselected-at-the-destination\",\n \"select-all-in-a-panel-excludes-disabled-items-from-both-the-denominator-and-the-count\",\n \"an-item-with-nothing-selected-in-its-panel-still-supports-direct-single-item-move\",\n \"search-and-pagination-inside-a-panel-are-product-composition-not-this-contract\",\n ],\n} as const satisfies BehaviorContract;\n"]}
|
|
1
|
+
{"version":3,"file":"transfer-list.js","sourceRoot":"","sources":["../src/transfer-list.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ColorReference } from \"./color-references.js\";\nimport type {\n BehaviorContract,\n CheckboxState,\n CollectionKey,\n SelectItemDescriptor,\n} from \"./behaviors.js\";\nimport {\n getCheckboxNextState,\n reconcileCheckboxSelection,\n toggleCheckboxSelection,\n} from \"./selection-helpers.js\";\nimport { collectionItemContract, focusIndicatorContract } from \"./component-contracts.js\";\nimport { validateCollection } from \"./collection.js\";\nimport { control, radius, spacing, stroke } from \"./foundations.js\";\nimport { semanticColors } from \"./semantic-colors.js\";\n\n/**\n * `docs/transfer-list.md`: two lists sharing one item set, split by whether\n * each id is in `targetKeys`. This is the same shape CheckboxGroup already\n * commits to (`ReadonlySet<Id>`, no third \"which panel\" enum to keep in\n * sync with membership) — one source of truth instead of two arrays that can\n * drift apart when an item is moved.\n */\nexport type TransferListPanel = \"source\" | \"target\";\n\nexport type TransferListDescriptor<Id extends CollectionKey = CollectionKey> = Readonly<{\n items: readonly SelectItemDescriptor<Id>[];\n targetKeys: ReadonlySet<Id>;\n}>;\n\nexport type TransferListSelection<Id extends CollectionKey = CollectionKey> = Readonly<{\n source: ReadonlySet<Id>;\n target: ReadonlySet<Id>;\n}>;\n\nfunction withPanelSelection<Id extends CollectionKey>(\n selection: TransferListSelection<Id>,\n panel: TransferListPanel,\n next: ReadonlySet<Id>,\n): TransferListSelection<Id> {\n return panel === \"source\"\n ? { source: next, target: selection.target }\n : { source: selection.source, target: next };\n}\n\nfunction assertKnownIds<Id extends CollectionKey>(\n label: string,\n ids: ReadonlySet<Id>,\n knownIds: ReadonlySet<Id>,\n): void {\n for (const id of ids) {\n if (!knownIds.has(id)) {\n throw new RangeError(`TransferList ${label} references an unknown item id: ${id}`);\n }\n }\n}\n\n/** An item already sitting entirely inside one panel (including all-in-target\n * or all-in-source) is valid — nothing here requires either panel to be\n * non-empty, and a disabled item is valid in either panel even though it can\n * never be moved by the UI. */\nexport function validateTransferListDescriptor<Id extends CollectionKey>(\n descriptor: TransferListDescriptor<Id>,\n): void {\n validateCollection({ items: descriptor.items });\n const knownIds = new Set(descriptor.items.map((item) => item.id));\n assertKnownIds(\"targetKeys\", descriptor.targetKeys, knownIds);\n}\n\nexport type TransferListPanels<Id extends CollectionKey = CollectionKey> = Readonly<{\n source: readonly SelectItemDescriptor<Id>[];\n target: readonly SelectItemDescriptor<Id>[];\n}>;\n\n/** Splits by `targetKeys` membership, preserving each item's relative order from `items`. */\nexport function resolveTransferListPanels<Id extends CollectionKey>(\n descriptor: TransferListDescriptor<Id>,\n): TransferListPanels<Id> {\n validateTransferListDescriptor(descriptor);\n const source: SelectItemDescriptor<Id>[] = [];\n const target: SelectItemDescriptor<Id>[] = [];\n for (const item of descriptor.items) {\n (descriptor.targetKeys.has(item.id) ? target : source).push(item);\n }\n return { source, target };\n}\n\nexport function validateTransferListSelection<Id extends CollectionKey>(\n descriptor: TransferListDescriptor<Id>,\n selection: TransferListSelection<Id>,\n): void {\n const panels = resolveTransferListPanels(descriptor);\n assertKnownIds(\"selection.source\", selection.source, new Set(panels.source.map((i) => i.id)));\n assertKnownIds(\"selection.target\", selection.target, new Set(panels.target.map((i) => i.id)));\n}\n\n/** Toggles one row's checkbox within its own panel; the other panel's selection is untouched. */\nexport function toggleTransferListSelection<Id extends CollectionKey>(\n descriptor: TransferListDescriptor<Id>,\n selection: TransferListSelection<Id>,\n panel: TransferListPanel,\n id: Id,\n): TransferListSelection<Id> {\n const panels = resolveTransferListPanels(descriptor);\n const next = toggleCheckboxSelection(panels[panel], selection[panel], id);\n return withPanelSelection(selection, panel, next);\n}\n\n/**\n * Same tri-state `CheckboxState` `resolveDataTableSelectAllState` derives for\n * a table header — disabled rows excluded from both the denominator and the\n * count — generalized from \"all rows\" to \"this one panel's rows\".\n */\nexport function resolveTransferListSelectAllState<Id extends CollectionKey>(\n descriptor: TransferListDescriptor<Id>,\n selection: TransferListSelection<Id>,\n panel: TransferListPanel,\n): CheckboxState {\n const items = resolveTransferListPanels(descriptor)[panel];\n const selectable = items.filter((item) => !item.disabled);\n if (selectable.length === 0) return false;\n const selectedCount = selectable.filter((item) => selection[panel].has(item.id)).length;\n if (selectedCount === 0) return false;\n return selectedCount === selectable.length ? true : \"mixed\";\n}\n\n/** Mixed-defaults-to-checked, matching `getCheckboxNextState`'s existing convention. */\nexport function toggleTransferListSelectAll<Id extends CollectionKey>(\n descriptor: TransferListDescriptor<Id>,\n selection: TransferListSelection<Id>,\n panel: TransferListPanel,\n): TransferListSelection<Id> {\n const current = resolveTransferListSelectAllState(descriptor, selection, panel);\n const checkAll = getCheckboxNextState(current);\n const items = resolveTransferListPanels(descriptor)[panel];\n const next = checkAll\n ? new Set(items.filter((item) => !item.disabled).map((item) => item.id))\n : new Set<Id>();\n return withPanelSelection(selection, panel, next);\n}\n\nexport type TransferListMoveDirection = \"toTarget\" | \"toSource\";\n\nexport type TransferListMoveResult<Id extends CollectionKey = CollectionKey> = Readonly<{\n targetKeys: ReadonlySet<Id>;\n selection: TransferListSelection<Id>;\n /** In origin-panel order — the product formats the announcement string from this. */\n movedIds: readonly Id[];\n}>;\n\n/**\n * Moves every enabled, currently-selected id out of its origin panel.\n * Disabled ids are skipped rather than rejected (a disabled row can never\n * enter a selection through `toggleTransferListSelection`, but a product\n * could hand one to `defaultSelectedKeys`, and skipping mirrors\n * `toggleTreeCheckedSelection`'s disabled guard rather than throwing on it).\n * Moved ids are cleared from the origin panel's selection and deliberately\n * left unselected in the destination panel — a move commits a value, it does\n * not also commit a new pending selection the user did not make.\n */\nexport function moveTransferListSelection<Id extends CollectionKey>(\n descriptor: TransferListDescriptor<Id>,\n selection: TransferListSelection<Id>,\n direction: TransferListMoveDirection,\n): TransferListMoveResult<Id> {\n validateTransferListSelection(descriptor, selection);\n const fromPanel: TransferListPanel = direction === \"toTarget\" ? \"source\" : \"target\";\n const fromItems = resolveTransferListPanels(descriptor)[fromPanel];\n const movedIds = fromItems\n .filter((item) => !item.disabled && selection[fromPanel].has(item.id))\n .map((item) => item.id);\n\n if (movedIds.length === 0) {\n return { targetKeys: descriptor.targetKeys, selection, movedIds: [] };\n }\n\n const movedIdSet = new Set(movedIds);\n const targetKeys =\n direction === \"toTarget\"\n ? new Set([...descriptor.targetKeys, ...movedIds])\n : new Set([...descriptor.targetKeys].filter((id) => !movedIdSet.has(id)));\n\n const nextFromSelection = new Set(\n [...selection[fromPanel]].filter((id) => !movedIdSet.has(id)),\n );\n return {\n targetKeys,\n selection: withPanelSelection(selection, fromPanel, nextFromSelection),\n movedIds,\n };\n}\n\n/**\n * Where focus lands once the moved rows are gone from a panel: the item that\n * slid into the first removed row's position, so keyboard users keep moving\n * down the list without their focus jumping to the top or vanishing. `null`\n * means the panel is now empty — the renderer falls back to the panel's\n * empty-state message or the move button, never to the document body.\n */\nexport function resolveTransferListFocusAfterMove<Id extends CollectionKey>(\n remainingPanelItems: readonly SelectItemDescriptor<Id>[],\n removedIndex: number,\n): Id | null {\n if (remainingPanelItems.length === 0) return null;\n const clamped = Math.min(Math.max(removedIndex, 0), remainingPanelItems.length - 1);\n return remainingPanelItems[clamped]!.id;\n}\n\n/** Drops selected ids that left either panel (item removed from `items` entirely). */\nexport function reconcileTransferListSelection<Id extends CollectionKey>(\n descriptor: TransferListDescriptor<Id>,\n selection: TransferListSelection<Id>,\n): TransferListSelection<Id> {\n const panels = resolveTransferListPanels(descriptor);\n const source = reconcileCheckboxSelection(panels.source, selection.source);\n const target = reconcileCheckboxSelection(panels.target, selection.target);\n if (source === selection.source && target === selection.target) return selection;\n return { source, target };\n}\n\nexport const transferListRecipe = {\n slots: [\n \"root\",\n \"panel\",\n \"panelHeader\",\n \"panelTitle\",\n \"panelCount\",\n \"list\",\n \"item\",\n \"itemCheckbox\",\n \"emptyState\",\n \"moveControls\",\n \"moveButton\",\n ] as const,\n panel: {\n background: semanticColors.canvas,\n border: semanticColors.border.default,\n borderWidth: stroke.default,\n radius: \"md\" as const,\n },\n panelHeader: {\n minHeight: 44,\n paddingHorizontal: spacing.sm,\n title: { color: semanticColors.content.body, textVariant: \"body\" as const },\n count: { color: semanticColors.content.secondary, textVariant: \"label\" as const },\n },\n item: collectionItemContract,\n emptyState: { color: semanticColors.content.secondary, textVariant: \"label\" as const },\n // The move buttons always stack (beside or between the panels), so they take the stacked-button gap.\n moveControls: { gap: spacing.xs },\n moveButton: {\n minTarget: control.minTouchTarget,\n color: semanticColors.content.brand,\n disabledOpacity: 0.4,\n },\n states: { focus: focusIndicatorContract },\n} as const satisfies {\n slots: readonly [\n \"root\",\n \"panel\",\n \"panelHeader\",\n \"panelTitle\",\n \"panelCount\",\n \"list\",\n \"item\",\n \"itemCheckbox\",\n \"emptyState\",\n \"moveControls\",\n \"moveButton\",\n ];\n panel: { background: ColorReference; border: ColorReference; borderWidth: number; radius: keyof typeof radius };\n panelHeader: {\n minHeight: number;\n paddingHorizontal: number;\n title: { color: ColorReference; textVariant: \"body\" };\n count: { color: ColorReference; textVariant: \"label\" };\n };\n item: typeof collectionItemContract;\n emptyState: { color: ColorReference; textVariant: \"label\" };\n moveControls: { gap: number };\n moveButton: { minTarget: number; color: ColorReference; disabledOpacity: number };\n states: { focus: typeof focusIndicatorContract };\n};\n\nexport const transferListBehavior = {\n controlled: [\"targetKeys\", \"defaultTargetKeys\", \"onTargetKeysChange\"],\n inputs: [\"items\"],\n events: [\"onMove\"],\n stateAxes: {\n availability: [\"enabled\", \"disabled\"],\n value: [\"empty\", \"filled\", \"selected\", \"mixed\"],\n },\n web: {\n roles: [\"group\", \"listbox\", \"option\", \"checkbox\", \"button\"],\n keyboard: [\"Tab\", \"Space\", \"Enter\", \"ArrowUp\", \"ArrowDown\", \"Home\", \"End\"],\n focus: \"roving\",\n },\n native: {\n roles: [\"list\", \"checkbox\", \"button\"],\n states: [\"disabled\", \"selected\", \"checked\"],\n actions: [\"toggle\", \"toggleSelectAll\", \"moveSelection\", \"moveItem\"],\n },\n scenarios: [\n \"moving-is-reachable-entirely-by-keyboard-select-with-space-then-activate-the-move-button\",\n \"moving-a-single-focused-row-does-not-require-first-opening-multi-select\",\n \"focus-after-a-move-lands-on-the-item-that-slid-into-the-removed-rows-position\",\n \"focus-after-emptying-a-panel-falls-back-to-its-empty-state-never-lost-to-the-document\",\n \"every-move-emits-which-ids-moved-so-the-product-can-announce-a-formatted-sentence\",\n \"disabled-items-are-never-selectable-and-never-move\",\n \"moved-items-are-cleared-from-the-origin-panels-selection-and-left-unselected-at-the-destination\",\n \"select-all-in-a-panel-excludes-disabled-items-from-both-the-denominator-and-the-count\",\n \"an-item-with-nothing-selected-in-its-panel-still-supports-direct-single-item-move\",\n \"search-and-pagination-inside-a-panel-are-product-composition-not-this-contract\",\n ],\n} as const satisfies BehaviorContract;\n"]}
|
package/dist/upload-item.d.ts
CHANGED
|
@@ -125,18 +125,9 @@ export declare const uploadItemRecipe: {
|
|
|
125
125
|
readonly tone: "brand";
|
|
126
126
|
readonly errorTone: "danger";
|
|
127
127
|
};
|
|
128
|
+
/** Cancel/retry render as ghost IconButtons named by their labels; the button recipe owns color (2026-10-17). */
|
|
128
129
|
readonly action: {
|
|
129
130
|
readonly minTarget: 44;
|
|
130
|
-
readonly color: Readonly<{
|
|
131
|
-
source: "theme";
|
|
132
|
-
key: "contentBrand";
|
|
133
|
-
alpha?: number;
|
|
134
|
-
}>;
|
|
135
|
-
readonly dangerColor: Readonly<{
|
|
136
|
-
source: "theme";
|
|
137
|
-
key: "danger";
|
|
138
|
-
alpha?: number;
|
|
139
|
-
}>;
|
|
140
131
|
};
|
|
141
132
|
readonly states: {
|
|
142
133
|
readonly focus: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upload-item.d.ts","sourceRoot":"","sources":["../src/upload-item.ts"],"names":[],"mappings":"AAWA,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,OAAO,CAAC;AAE7E,MAAM,MAAM,sBAAsB,GAAG,QAAQ,CAAC;IAAE,MAAM,EAAE,SAAS,CAAA;CAAE,CAAC,CAAC;AAErE,MAAM,MAAM,wBAAwB,GAAG,QAAQ,CAAC;IAC9C,MAAM,EAAE,WAAW,CAAC;IACpB,qFAAqF;IACrF,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,kEAAkE;IAClE,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC,CAAC;AAEH,MAAM,MAAM,sBAAsB,GAAG,QAAQ,CAAC;IAAE,MAAM,EAAE,SAAS,CAAA;CAAE,CAAC,CAAC;AAErE,MAAM,MAAM,oBAAoB,GAAG,QAAQ,CAAC;IAC1C,MAAM,EAAE,OAAO,CAAC;IAChB,4EAA4E;IAC5E,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC,CAAC;AAEH;;;;;GAKG;AACH,MAAM,MAAM,eAAe,GACvB,sBAAsB,GACtB,wBAAwB,GACxB,sBAAsB,GACtB,oBAAoB,CAAC;AAEzB,MAAM,MAAM,oBAAoB,GAAG,QAAQ,CAAC;IAC1C,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,eAAe,CAAC;CACxB,CAAC,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,uEAAuE;IACvE,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf,CAAC,CAAC;AAQH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI,CAoBpE;AAED,wBAAgB,4BAA4B,CAAC,UAAU,EAAE,oBAAoB,GAAG,IAAI,CAKnF;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI,CAIvE;AAED,sFAAsF;AACtF,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,SAAS,oBAAoB,EAAE,GAAG,IAAI,CASnF;AAED,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,OAAO,CAAC;AAElD;;;;GAIG;AACH,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,eAAe,GAAG,gBAAgB,GAAG,IAAI,CAI5F;AAED,MAAM,MAAM,sBAAsB,GAAG,QAAQ,CAAC;IAC5C,yFAAyF;IACzF,KAAK,EAAE,MAAM,CAAC;IACd,iEAAiE;IACjE,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC,CAAC;AAEH;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAC3C,UAAU,EAAE,oBAAoB,EAChC,MAAM,EAAE,gBAAgB,GACvB,sBAAsB,CAmBxB;AAED,eAAO,MAAM,gBAAgB;;;;;;;;QAMzB;;;WAGG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAaL,iEAAiE
|
|
1
|
+
{"version":3,"file":"upload-item.d.ts","sourceRoot":"","sources":["../src/upload-item.ts"],"names":[],"mappings":"AAWA,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,OAAO,CAAC;AAE7E,MAAM,MAAM,sBAAsB,GAAG,QAAQ,CAAC;IAAE,MAAM,EAAE,SAAS,CAAA;CAAE,CAAC,CAAC;AAErE,MAAM,MAAM,wBAAwB,GAAG,QAAQ,CAAC;IAC9C,MAAM,EAAE,WAAW,CAAC;IACpB,qFAAqF;IACrF,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,kEAAkE;IAClE,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC,CAAC;AAEH,MAAM,MAAM,sBAAsB,GAAG,QAAQ,CAAC;IAAE,MAAM,EAAE,SAAS,CAAA;CAAE,CAAC,CAAC;AAErE,MAAM,MAAM,oBAAoB,GAAG,QAAQ,CAAC;IAC1C,MAAM,EAAE,OAAO,CAAC;IAChB,4EAA4E;IAC5E,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC,CAAC;AAEH;;;;;GAKG;AACH,MAAM,MAAM,eAAe,GACvB,sBAAsB,GACtB,wBAAwB,GACxB,sBAAsB,GACtB,oBAAoB,CAAC;AAEzB,MAAM,MAAM,oBAAoB,GAAG,QAAQ,CAAC;IAC1C,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,eAAe,CAAC;CACxB,CAAC,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,uEAAuE;IACvE,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf,CAAC,CAAC;AAQH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI,CAoBpE;AAED,wBAAgB,4BAA4B,CAAC,UAAU,EAAE,oBAAoB,GAAG,IAAI,CAKnF;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI,CAIvE;AAED,sFAAsF;AACtF,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,SAAS,oBAAoB,EAAE,GAAG,IAAI,CASnF;AAED,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,OAAO,CAAC;AAElD;;;;GAIG;AACH,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,eAAe,GAAG,gBAAgB,GAAG,IAAI,CAI5F;AAED,MAAM,MAAM,sBAAsB,GAAG,QAAQ,CAAC;IAC5C,yFAAyF;IACzF,KAAK,EAAE,MAAM,CAAC;IACd,iEAAiE;IACjE,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC,CAAC;AAEH;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAC3C,UAAU,EAAE,oBAAoB,EAChC,MAAM,EAAE,gBAAgB,GACvB,sBAAsB,CAmBxB;AAED,eAAO,MAAM,gBAAgB;;;;;;;;QAMzB;;;WAGG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAaL,iEAAiE;;;;;;IAMjE,iHAAiH;;;;;;;;;;;;;;;;CA2BlH,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;CA0BM,CAAC"}
|
package/dist/upload-item.js
CHANGED
|
@@ -116,10 +116,9 @@ export const uploadItemRecipe = {
|
|
|
116
116
|
tone: progressRecipe.defaults.tone,
|
|
117
117
|
errorTone: "danger",
|
|
118
118
|
},
|
|
119
|
+
/** Cancel/retry render as ghost IconButtons named by their labels; the button recipe owns color (2026-10-17). */
|
|
119
120
|
action: {
|
|
120
121
|
minTarget: control.minTouchTarget,
|
|
121
|
-
color: semanticColors.content.brand,
|
|
122
|
-
dangerColor: semanticColors.content.danger,
|
|
123
122
|
},
|
|
124
123
|
states: {
|
|
125
124
|
focus: focusIndicatorContract,
|
package/dist/upload-item.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upload-item.js","sourceRoot":"","sources":["../src/upload-item.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ColorReference } from \"./color-references.js\";\nimport type { BehaviorContract } from \"./behaviors.js\";\nimport { focusIndicatorContract } from \"./component-contracts.js\";\nimport {\n progressRecipe,\n type ProgressSize,\n type ProgressTone,\n} from \"./progress-recipe.js\";\nimport { control, layout, opacity, radius, spacing, type TextVariant } from \"./foundations.js\";\nimport { semanticColors } from \"./semantic-colors.js\";\n\nexport type UploadItemStatus = \"pending\" | \"uploading\" | \"success\" | \"error\";\n\nexport type UploadItemPendingState = Readonly<{ status: \"pending\" }>;\n\nexport type UploadItemUploadingState = Readonly<{\n status: \"uploading\";\n /** Product-measured transfer fraction. `null` means indeterminate — size unknown. */\n progress: number | null;\n /** Product-formatted announcement, e.g. \"1.6MB / 3.2MB 업로드 중\". */\n progressLabel?: string;\n}>;\n\nexport type UploadItemSuccessState = Readonly<{ status: \"success\" }>;\n\nexport type UploadItemErrorState = Readonly<{\n status: \"error\";\n /** States the problem and the next action, e.g. \"네트워크 오류입니다. 다시 시도해주세요.\" */\n message: string;\n}>;\n\n/**\n * Cancel and retry are never stored as separate booleans: deriving them from\n * `status` (see `getUploadItemAvailableAction`) makes \"cancel while error\" or\n * \"retry while uploading\" unrepresentable, the same way `SheetOpenState` and\n * `LoadMoreState` close off invalid combinations by construction.\n */\nexport type UploadItemState =\n | UploadItemPendingState\n | UploadItemUploadingState\n | UploadItemSuccessState\n | UploadItemErrorState;\n\nexport type UploadItemDescriptor = Readonly<{\n id: string;\n name: string;\n /** Product-formatted size, e.g. \"1.2 MB\" — HJM does not format bytes. */\n sizeLabel?: string;\n state: UploadItemState;\n}>;\n\nexport type UploadItemLabels = Readonly<{\n pending: string;\n /** Fallback when `progress` is `null` or `progressLabel` is absent. */\n uploading: string;\n success: string;\n cancel: string;\n retry: string;\n}>;\n\nfunction assertNonEmpty(value: string, field: string): void {\n if (typeof value !== \"string\" || value.trim().length === 0) {\n throw new TypeError(`UploadItem ${field} must not be empty`);\n }\n}\n\nexport function validateUploadItemState(state: UploadItemState): void {\n const status = (state as Readonly<{ status?: unknown }>).status;\n if (\n status !== \"pending\" &&\n status !== \"uploading\" &&\n status !== \"success\" &&\n status !== \"error\"\n ) {\n throw new TypeError(`Unsupported UploadItem status: ${String(status)}`);\n }\n if (status === \"uploading\") {\n const { progress, progressLabel } = state as UploadItemUploadingState;\n if (progress !== null && (!Number.isFinite(progress) || progress < 0 || progress > 1)) {\n throw new RangeError(\"UploadItem progress must be null or a number between 0 and 1\");\n }\n if (progressLabel !== undefined) assertNonEmpty(progressLabel, \"progressLabel\");\n }\n if (status === \"error\") {\n assertNonEmpty((state as UploadItemErrorState).message, \"error state message\");\n }\n}\n\nexport function validateUploadItemDescriptor(descriptor: UploadItemDescriptor): void {\n assertNonEmpty(descriptor.id, \"id\");\n assertNonEmpty(descriptor.name, \"name\");\n if (descriptor.sizeLabel !== undefined) assertNonEmpty(descriptor.sizeLabel, \"sizeLabel\");\n validateUploadItemState(descriptor.state);\n}\n\nexport function validateUploadItemLabels(labels: UploadItemLabels): void {\n for (const field of [\"pending\", \"uploading\", \"success\", \"cancel\", \"retry\"] as const) {\n assertNonEmpty(labels[field], `labels.${field}`);\n }\n}\n\n/** Rejects duplicate stable ids so a rendered list never desyncs a row's identity. */\nexport function validateUploadItemList(items: readonly UploadItemDescriptor[]): void {\n const ids = new Set<string>();\n for (const item of items) {\n validateUploadItemDescriptor(item);\n if (ids.has(item.id)) {\n throw new TypeError(`Duplicate UploadItem id: ${item.id}`);\n }\n ids.add(item.id);\n }\n}\n\nexport type UploadItemAction = \"cancel\" | \"retry\";\n\n/**\n * The only place cancel/retry availability is computed. Renderers must not\n * keep their own copy of this rule — it would drift from `status` the first\n * time a new state is added.\n */\nexport function getUploadItemAvailableAction(state: UploadItemState): UploadItemAction | null {\n if (state.status === \"uploading\") return \"cancel\";\n if (state.status === \"error\") return \"retry\";\n return null;\n}\n\nexport type UploadItemAnnouncement = Readonly<{\n /** Accessible name — the file name, kept independent of status (Statistic precedent). */\n label: string;\n /** Accessible description/live-region text. Never color-only. */\n description: string;\n}>;\n\n/**\n * Falls back to a rounded percent when a product supplies numeric `progress`\n * but no `progressLabel` — the one place this module computes visible copy\n * itself, mirroring Slider's raw-value fallback rather than Statistic's\n * strict \"product always formats\" rule, because an uploading row with no\n * numeric feedback at all is a worse default than a plain percentage.\n */\nexport function resolveUploadItemAnnouncement(\n descriptor: UploadItemDescriptor,\n labels: UploadItemLabels,\n): UploadItemAnnouncement {\n validateUploadItemDescriptor(descriptor);\n validateUploadItemLabels(labels);\n const { state } = descriptor;\n if (state.status === \"pending\") {\n return { label: descriptor.name, description: labels.pending };\n }\n if (state.status === \"uploading\") {\n if (state.progressLabel) {\n return { label: descriptor.name, description: state.progressLabel };\n }\n const description =\n state.progress === null ? labels.uploading : `${Math.round(state.progress * 100)}%`;\n return { label: descriptor.name, description };\n }\n if (state.status === \"success\") {\n return { label: descriptor.name, description: labels.success };\n }\n return { label: descriptor.name, description: state.message };\n}\n\nexport const uploadItemRecipe = {\n slots: [\"root\", \"icon\", \"name\", \"meta\", \"progress\", \"statusText\", \"cancel\", \"retry\"] as const,\n defaults: { size: \"medium\" },\n row: {\n minHeight: layout.rowHeight.twoLine,\n paddingHorizontal: spacing.md,\n /**\n * Added 2026-10-06: Native hard-coded 8 and Web used 12 with a 64px floor, so the same row\n * measured 68 on Native and 64-ish+ on Web. One value now drives both renderers.\n */\n paddingVertical: spacing.xs,\n gap: spacing.sm,\n radius: \"md\",\n },\n name: { color: semanticColors.content.body, textVariant: \"body\" },\n meta: { color: semanticColors.content.secondary, textVariant: \"label\" },\n statusTones: {\n pending: semanticColors.content.secondary,\n uploading: semanticColors.content.brand,\n success: semanticColors.feedback.success.foreground,\n error: semanticColors.content.danger,\n },\n /** Reuses `progressRecipe` verbatim — no second progress bar. */\n progress: {\n size: progressRecipe.defaults.size,\n tone: progressRecipe.defaults.tone,\n errorTone: \"danger\",\n },\n action: {\n minTarget: control.minTouchTarget,\n color: semanticColors.content.brand,\n dangerColor: semanticColors.content.danger,\n },\n states: {\n focus: focusIndicatorContract,\n disabledOpacity: opacity.disabled,\n },\n} as const satisfies {\n slots: readonly [\n \"root\",\n \"icon\",\n \"name\",\n \"meta\",\n \"progress\",\n \"statusText\",\n \"cancel\",\n \"retry\",\n ];\n defaults: { size: \"medium\" };\n row: { minHeight: number; paddingHorizontal: number; paddingVertical: number; gap: number; radius: keyof typeof radius };\n name: { color: ColorReference; textVariant: TextVariant };\n meta: { color: ColorReference; textVariant: TextVariant };\n statusTones: Record<UploadItemStatus, ColorReference>;\n progress: { size: ProgressSize; tone: ProgressTone; errorTone: ProgressTone };\n action: { minTarget: number; color: ColorReference; dangerColor: ColorReference };\n states: { focus: typeof focusIndicatorContract; disabledOpacity: number };\n};\n\n/**\n * `stateAxes.content` maps status onto the common axis\n * (pending→idle, uploading→loading, success→complete, error→error).\n * `loadingMore`/`empty` do not apply — one row is never paginated.\n */\nexport const uploadItemBehavior = {\n controlled: [],\n inputs: [\"descriptor\", \"labels\"],\n events: [\"onCancel\", \"onRetry\"],\n stateAxes: {\n content: [\"idle\", \"loading\", \"complete\", \"error\"],\n },\n web: {\n roles: [\"group\", \"progressbar\", \"button\"],\n keyboard: [\"Tab\", \"Enter\", \"Space\"],\n focus: \"native\",\n },\n native: {\n roles: [\"progressbar\", \"button\"],\n states: [\"busy\"],\n actions: [\"cancel\", \"retry\"],\n },\n scenarios: [\n \"progress-is-announced-as-a-sentence-not-only-a-filled-bar\",\n \"cancel-is-reachable-only-while-uploading\",\n \"retry-is-reachable-only-while-error\",\n \"pending-and-success-expose-no-destructive-or-retry-action\",\n \"indeterminate-progress-falls-back-to-a-static-uploading-label\",\n \"reuses-the-shared-progress-recipe-instead-of-a-new-bar\",\n \"duplicate-ids-in-a-rendered-list-are-rejected\",\n ],\n} as const satisfies BehaviorContract;\n"]}
|
|
1
|
+
{"version":3,"file":"upload-item.js","sourceRoot":"","sources":["../src/upload-item.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ColorReference } from \"./color-references.js\";\nimport type { BehaviorContract } from \"./behaviors.js\";\nimport { focusIndicatorContract } from \"./component-contracts.js\";\nimport {\n progressRecipe,\n type ProgressSize,\n type ProgressTone,\n} from \"./progress-recipe.js\";\nimport { control, layout, opacity, radius, spacing, type TextVariant } from \"./foundations.js\";\nimport { semanticColors } from \"./semantic-colors.js\";\n\nexport type UploadItemStatus = \"pending\" | \"uploading\" | \"success\" | \"error\";\n\nexport type UploadItemPendingState = Readonly<{ status: \"pending\" }>;\n\nexport type UploadItemUploadingState = Readonly<{\n status: \"uploading\";\n /** Product-measured transfer fraction. `null` means indeterminate — size unknown. */\n progress: number | null;\n /** Product-formatted announcement, e.g. \"1.6MB / 3.2MB 업로드 중\". */\n progressLabel?: string;\n}>;\n\nexport type UploadItemSuccessState = Readonly<{ status: \"success\" }>;\n\nexport type UploadItemErrorState = Readonly<{\n status: \"error\";\n /** States the problem and the next action, e.g. \"네트워크 오류입니다. 다시 시도해주세요.\" */\n message: string;\n}>;\n\n/**\n * Cancel and retry are never stored as separate booleans: deriving them from\n * `status` (see `getUploadItemAvailableAction`) makes \"cancel while error\" or\n * \"retry while uploading\" unrepresentable, the same way `SheetOpenState` and\n * `LoadMoreState` close off invalid combinations by construction.\n */\nexport type UploadItemState =\n | UploadItemPendingState\n | UploadItemUploadingState\n | UploadItemSuccessState\n | UploadItemErrorState;\n\nexport type UploadItemDescriptor = Readonly<{\n id: string;\n name: string;\n /** Product-formatted size, e.g. \"1.2 MB\" — HJM does not format bytes. */\n sizeLabel?: string;\n state: UploadItemState;\n}>;\n\nexport type UploadItemLabels = Readonly<{\n pending: string;\n /** Fallback when `progress` is `null` or `progressLabel` is absent. */\n uploading: string;\n success: string;\n cancel: string;\n retry: string;\n}>;\n\nfunction assertNonEmpty(value: string, field: string): void {\n if (typeof value !== \"string\" || value.trim().length === 0) {\n throw new TypeError(`UploadItem ${field} must not be empty`);\n }\n}\n\nexport function validateUploadItemState(state: UploadItemState): void {\n const status = (state as Readonly<{ status?: unknown }>).status;\n if (\n status !== \"pending\" &&\n status !== \"uploading\" &&\n status !== \"success\" &&\n status !== \"error\"\n ) {\n throw new TypeError(`Unsupported UploadItem status: ${String(status)}`);\n }\n if (status === \"uploading\") {\n const { progress, progressLabel } = state as UploadItemUploadingState;\n if (progress !== null && (!Number.isFinite(progress) || progress < 0 || progress > 1)) {\n throw new RangeError(\"UploadItem progress must be null or a number between 0 and 1\");\n }\n if (progressLabel !== undefined) assertNonEmpty(progressLabel, \"progressLabel\");\n }\n if (status === \"error\") {\n assertNonEmpty((state as UploadItemErrorState).message, \"error state message\");\n }\n}\n\nexport function validateUploadItemDescriptor(descriptor: UploadItemDescriptor): void {\n assertNonEmpty(descriptor.id, \"id\");\n assertNonEmpty(descriptor.name, \"name\");\n if (descriptor.sizeLabel !== undefined) assertNonEmpty(descriptor.sizeLabel, \"sizeLabel\");\n validateUploadItemState(descriptor.state);\n}\n\nexport function validateUploadItemLabels(labels: UploadItemLabels): void {\n for (const field of [\"pending\", \"uploading\", \"success\", \"cancel\", \"retry\"] as const) {\n assertNonEmpty(labels[field], `labels.${field}`);\n }\n}\n\n/** Rejects duplicate stable ids so a rendered list never desyncs a row's identity. */\nexport function validateUploadItemList(items: readonly UploadItemDescriptor[]): void {\n const ids = new Set<string>();\n for (const item of items) {\n validateUploadItemDescriptor(item);\n if (ids.has(item.id)) {\n throw new TypeError(`Duplicate UploadItem id: ${item.id}`);\n }\n ids.add(item.id);\n }\n}\n\nexport type UploadItemAction = \"cancel\" | \"retry\";\n\n/**\n * The only place cancel/retry availability is computed. Renderers must not\n * keep their own copy of this rule — it would drift from `status` the first\n * time a new state is added.\n */\nexport function getUploadItemAvailableAction(state: UploadItemState): UploadItemAction | null {\n if (state.status === \"uploading\") return \"cancel\";\n if (state.status === \"error\") return \"retry\";\n return null;\n}\n\nexport type UploadItemAnnouncement = Readonly<{\n /** Accessible name — the file name, kept independent of status (Statistic precedent). */\n label: string;\n /** Accessible description/live-region text. Never color-only. */\n description: string;\n}>;\n\n/**\n * Falls back to a rounded percent when a product supplies numeric `progress`\n * but no `progressLabel` — the one place this module computes visible copy\n * itself, mirroring Slider's raw-value fallback rather than Statistic's\n * strict \"product always formats\" rule, because an uploading row with no\n * numeric feedback at all is a worse default than a plain percentage.\n */\nexport function resolveUploadItemAnnouncement(\n descriptor: UploadItemDescriptor,\n labels: UploadItemLabels,\n): UploadItemAnnouncement {\n validateUploadItemDescriptor(descriptor);\n validateUploadItemLabels(labels);\n const { state } = descriptor;\n if (state.status === \"pending\") {\n return { label: descriptor.name, description: labels.pending };\n }\n if (state.status === \"uploading\") {\n if (state.progressLabel) {\n return { label: descriptor.name, description: state.progressLabel };\n }\n const description =\n state.progress === null ? labels.uploading : `${Math.round(state.progress * 100)}%`;\n return { label: descriptor.name, description };\n }\n if (state.status === \"success\") {\n return { label: descriptor.name, description: labels.success };\n }\n return { label: descriptor.name, description: state.message };\n}\n\nexport const uploadItemRecipe = {\n slots: [\"root\", \"icon\", \"name\", \"meta\", \"progress\", \"statusText\", \"cancel\", \"retry\"] as const,\n defaults: { size: \"medium\" },\n row: {\n minHeight: layout.rowHeight.twoLine,\n paddingHorizontal: spacing.md,\n /**\n * Added 2026-10-06: Native hard-coded 8 and Web used 12 with a 64px floor, so the same row\n * measured 68 on Native and 64-ish+ on Web. One value now drives both renderers.\n */\n paddingVertical: spacing.xs,\n gap: spacing.sm,\n radius: \"md\",\n },\n name: { color: semanticColors.content.body, textVariant: \"body\" },\n meta: { color: semanticColors.content.secondary, textVariant: \"label\" },\n statusTones: {\n pending: semanticColors.content.secondary,\n uploading: semanticColors.content.brand,\n success: semanticColors.feedback.success.foreground,\n error: semanticColors.content.danger,\n },\n /** Reuses `progressRecipe` verbatim — no second progress bar. */\n progress: {\n size: progressRecipe.defaults.size,\n tone: progressRecipe.defaults.tone,\n errorTone: \"danger\",\n },\n /** Cancel/retry render as ghost IconButtons named by their labels; the button recipe owns color (2026-10-17). */\n action: {\n minTarget: control.minTouchTarget,\n },\n states: {\n focus: focusIndicatorContract,\n disabledOpacity: opacity.disabled,\n },\n} as const satisfies {\n slots: readonly [\n \"root\",\n \"icon\",\n \"name\",\n \"meta\",\n \"progress\",\n \"statusText\",\n \"cancel\",\n \"retry\",\n ];\n defaults: { size: \"medium\" };\n row: { minHeight: number; paddingHorizontal: number; paddingVertical: number; gap: number; radius: keyof typeof radius };\n name: { color: ColorReference; textVariant: TextVariant };\n meta: { color: ColorReference; textVariant: TextVariant };\n statusTones: Record<UploadItemStatus, ColorReference>;\n progress: { size: ProgressSize; tone: ProgressTone; errorTone: ProgressTone };\n action: { minTarget: number };\n states: { focus: typeof focusIndicatorContract; disabledOpacity: number };\n};\n\n/**\n * `stateAxes.content` maps status onto the common axis\n * (pending→idle, uploading→loading, success→complete, error→error).\n * `loadingMore`/`empty` do not apply — one row is never paginated.\n */\nexport const uploadItemBehavior = {\n controlled: [],\n inputs: [\"descriptor\", \"labels\"],\n events: [\"onCancel\", \"onRetry\"],\n stateAxes: {\n content: [\"idle\", \"loading\", \"complete\", \"error\"],\n },\n web: {\n roles: [\"group\", \"progressbar\", \"button\"],\n keyboard: [\"Tab\", \"Enter\", \"Space\"],\n focus: \"native\",\n },\n native: {\n roles: [\"progressbar\", \"button\"],\n states: [\"busy\"],\n actions: [\"cancel\", \"retry\"],\n },\n scenarios: [\n \"progress-is-announced-as-a-sentence-not-only-a-filled-bar\",\n \"cancel-is-reachable-only-while-uploading\",\n \"retry-is-reachable-only-while-error\",\n \"pending-and-success-expose-no-destructive-or-retry-action\",\n \"indeterminate-progress-falls-back-to-a-static-uploading-label\",\n \"reuses-the-shared-progress-recipe-instead-of-a-new-bar\",\n \"duplicate-ids-in-a-rendered-list-are-rejected\",\n ],\n} as const satisfies BehaviorContract;\n"]}
|
package/dist/version.d.ts
CHANGED
package/dist/version.js
CHANGED
package/dist/version.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,MAAM,CAAC,MAAM,mBAAmB,GAAG,QAAiB,CAAC","sourcesContent":["/** Package release shown by documentation surfaces. Kept in sync by a test. */\nexport const designSystemVersion = \"1.
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,MAAM,CAAC,MAAM,mBAAmB,GAAG,QAAiB,CAAC","sourcesContent":["/** Package release shown by documentation surfaces. Kept in sync by a test. */\nexport const designSystemVersion = \"1.27.0\" as const;\n"]}
|
package/docs/activity-chip.md
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
# Activity chip
|
|
2
2
|
|
|
3
|
-
검토일: 2026-10-
|
|
3
|
+
검토일: 2026-10-17 · 제공 확인: 1.26.1(설치된 Web·Native 공개 타입 기준, 최초 출시 버전 아님)
|
|
4
4
|
|
|
5
5
|
2026-10-10 사용자 요청("칩이랑 패널 디자인시스템에 넣고 구성에 칩 누르면 나오게 하자 … 칩은 있으면 다른 이름으로
|
|
6
6
|
새로 만들고")으로 BurnTok 검수 상태 칩을 공통화했다. 기존 `Chip`은 행동/선택 칩이라 `radio`·`checkbox` 또는 단순
|
|
7
7
|
button 의미를 가진다. 이 칩은 **상세 패널을 여닫는 공개(disclosure) 트리거**라 `aria-expanded`/`expanded` 상태가 필요하고,
|
|
8
8
|
작은 장식 미디어와 한 줄 상태 문구를 가진다. Chip에 축을 더하면 선택 의미와 펼침 의미가 한 API에 섞이므로
|
|
9
|
-
`ActivityChip`으로 분리했다.
|
|
10
|
-
|
|
9
|
+
`ActivityChip`으로 분리했다. 공개 API 대응표에서는 supplemental로 분류하며, 이 분류는
|
|
10
|
+
Chip의 안정성을 상속하거나 독립적인 stable 승격을 뜻하지 않는다. 현재 지원은 Web·Native이고
|
|
11
|
+
기기 검증 제한은 아래 검증 범위를 따른다. 카탈로그 등록은 [공통 기준](stable-promotion.md#카탈로그-등록과-공개-api-분류)을 따른다.
|
|
11
12
|
|
|
12
13
|
계약과 두 renderer의 granular subpath는 `/activity-chip`이다(contracts는 root에서도 재노출). 추가 peer는 없다.
|
|
13
14
|
|
package/docs/catalog-freeze.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$comment": "카탈로그
|
|
2
|
+
"$comment": "종료된 카탈로그 동결의 역사 기록. 현재 등록 기준은 stable-promotion.md이며 이 목록으로 신규 등록을 차단하지 않는다.",
|
|
3
3
|
"frozenAt": "2026-09-26",
|
|
4
4
|
"reason": "2026-09-26 설계 점검: 111개 중 stable 4개였고, 세 제품 이상이 쓰는 약 30개가 beta에 묶여 있었다. 1.5.0에서 13개를 실제 증거로 승격했지만 입력·접근성 동작 증거가 필요한 핵심(Checkbox, Switch, Dialog, Sheet, SegmentedControl, RadioGroup, Link, PasswordField 등)은 아직 beta다. 폭을 넓히기 전에 이것들을 먼저 올린다.",
|
|
5
5
|
"unfreezeWhen": "위 핵심 beta가 stable이 되면 동결을 푼다. 그 전에 추가가 필요하면 이 파일의 exceptions에 이름·날짜·근거(ADR 또는 이슈)를 적는다.",
|
|
@@ -123,5 +123,8 @@
|
|
|
123
123
|
"VirtualList",
|
|
124
124
|
"VisuallyHidden",
|
|
125
125
|
"Watermark"
|
|
126
|
-
]
|
|
126
|
+
],
|
|
127
|
+
"status": "retired",
|
|
128
|
+
"retiredAt": "2026-10-17",
|
|
129
|
+
"resolution": "해제 조건에 열거한 Checkbox, Switch, Dialog, Sheet, SegmentedControl, RadioGroup, Link, PasswordField 모두 1.26.1 생성 manifest에서 Web·Native stable임을 확인. 원래 names·exceptions는 당시 결정 근거로 보존한다."
|
|
127
130
|
}
|
package/docs/chart.md
CHANGED
|
@@ -164,7 +164,7 @@
|
|
|
164
164
|
|
|
165
165
|
`Chart`는 2026-09-29에 지운 이름을 같은 이름으로 되살린다(`data-display`, Web·Native). 공개 컴포넌트 `LineChart`·`BarChart`·`PieChart`·
|
|
166
166
|
`RadarChart`·`ScatterChart`·`Sparkline`·`ChartLegend`는 이 한 계약의 동반 API다 — 같은 `ChartSeries` 모델·색 규칙·포커스·텍스트 대안을
|
|
167
|
-
공유하므로 종류마다 계약을 따로 두지 않는다.
|
|
167
|
+
공유하므로 종류마다 계약을 따로 두지 않는다. 당시 동결 예외는 `docs/catalog-freeze.json`에 보존하며 현재 등록은 [공통 기준](stable-promotion.md#카탈로그-등록과-공개-api-분류)을 따른다.
|
|
168
168
|
|
|
169
169
|
## Renderer와 검증
|
|
170
170
|
|
package/docs/consumer-policy.md
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
상태: **Normative**
|
|
4
4
|
정책 버전: **2.0.0**
|
|
5
|
-
검토일: 2026-10-
|
|
6
|
-
적용 대상: 신규 HJM Web·React Native 앱과 기존 앱의 새
|
|
5
|
+
검토일: 2026-10-17 · 현재 소비 계약과 변경 범위 검증
|
|
6
|
+
적용 대상: 신규 HJM Web·React Native 앱과 기존 앱의 새 화면. 기존 Flutter 제품의 별도 renderer 소비는 §1의 Flutter 경계를 따른다.
|
|
7
7
|
|
|
8
8
|
이 원문은 `@hjmds/design-contracts/consumer-policy.md`에서 제공한다. 소비 앱은 설치한
|
|
9
9
|
패키지 버전의 정책과 HJM-APP-STANDARD release snapshot을 함께 확인한다. 이 checkout의
|
|
@@ -20,10 +20,10 @@
|
|
|
20
20
|
|
|
21
21
|
## 1. 의존성과 버전
|
|
22
22
|
|
|
23
|
-
- 앱은 `@hjmds/design-contracts`와 한 renderer(`@hjmds/react` 또는
|
|
23
|
+
- Web·React Native 앱은 `@hjmds/design-contracts`와 한 renderer(`@hjmds/react` 또는
|
|
24
24
|
`@hjmds/react-native`)를 npm registry에서 설치해야 합니다(MUST).
|
|
25
25
|
- contracts와 renderer는 같은 정확한 SemVer여야 합니다(MUST). `^`, `~`, workspace·file,
|
|
26
|
-
Git ref와 tarball dependency는 허용하지 않습니다(MUST NOT).
|
|
26
|
+
Git ref와 tarball dependency는 이 npm 소비 경로에서 허용하지 않습니다(MUST NOT).
|
|
27
27
|
- 앱 runtime은 granular subpath를 우선하고 catalog·showcase·evidence entry는 CI나
|
|
28
28
|
tooling에서만 사용해야 합니다(SHOULD).
|
|
29
29
|
|
|
@@ -31,6 +31,12 @@
|
|
|
31
31
|
뜻하지 않는다. 2026-10-13 실제 package 의존성을 대조해 누락된 Utilverse와 App Release Hub를
|
|
32
32
|
추가했다. Hub는 정책 사이트 생성에 colors/foundations만 사용하므로 renderer 이관과 구분한다.
|
|
33
33
|
|
|
34
|
+
기존 Flutter 제품은 별도 `hjm_flutter` beta renderer를 사용한다. npm fixed train에 포함되지
|
|
35
|
+
않으며, 검토한 Git SHA와 `packages/flutter` 경로를 pubspec/lock에 고정한다. 공개 API와 지원
|
|
36
|
+
범위는 [고정 source의 Flutter README](https://github.com/jim1286/hjm-design-system/blob/dfe74c171809dd43e43aa08f127de20932cb8257/packages/flutter/README.md), 버전·SDK는 해당 pubspec이 소유한다.
|
|
37
|
+
2026-10-17 선택의창의 실제 Dart 소비를 대조해 module 계약에 Flutter 인터페이스와 소비자를
|
|
38
|
+
추가했다. pub.dev 게시나 npm renderer의 전체 API parity, 기기 검증 완료를 뜻하지 않는다.
|
|
39
|
+
|
|
34
40
|
## 2. 성숙도별 채택
|
|
35
41
|
|
|
36
42
|
| 사용할 surface 상태 | 신규 앱 기본 정책 | 추가 조건 |
|
|
@@ -54,8 +60,9 @@
|
|
|
54
60
|
[Stable Core 기록](stable-core.md)에 보존한다. 현재 규칙에 이전 버전의 개수나 임시 foundation
|
|
55
61
|
bridge를 복제하지 않는다. 구버전 소비자는 설치된 정책·profile과 해당 이관표를 확인한다.
|
|
56
62
|
|
|
57
|
-
화면은 [선택 기준](usage/SELECTION.md)에 따라 그대로 사용, 공개 슬롯 확장, 제품
|
|
58
|
-
|
|
63
|
+
화면은 [선택 기준](usage/SELECTION.md)에 따라 그대로 사용, 공개 슬롯 확장, 공통 API 보완, 제품 고유 기능 연결 중 고른다.
|
|
64
|
+
제품의 저장·권한 흐름은 제품이 연결하되, 공통 배치·상태 엔진이 부족하면 HJM API를 보완한다.
|
|
65
|
+
`children`·header·footer 슬롯이 있다는 이유로 공통 구조를 제품에서 다시 만들지 않는다.
|
|
59
66
|
|
|
60
67
|
## 3. 코드 경계
|
|
61
68
|
|
package/docs/description-list.md
CHANGED
|
@@ -72,3 +72,7 @@ Native의 라벨-값 접근성 노드와 text-scale 기반 열 전환은 rendere
|
|
|
72
72
|
과거 후보로 든 야잘알 화면은 단일 열 List/ListRow 조합이므로 DescriptionList 채택으로
|
|
73
73
|
세지 않는다. 제품의 1/2열 화면과 실제 기기 QA는 해당 앱 릴리스에서 확인하며,
|
|
74
74
|
[승격 기준](stable-promotion.md)에 따라 제품 채택 부재를 성숙도 관문으로 쓰지 않는다.
|
|
75
|
+
|
|
76
|
+
## 긴 기록의 가로 배치
|
|
77
|
+
|
|
78
|
+
2026-10-15 오늘야구 경기 요약에서 긴 기록의 항목 구분이 약했던 문제에 대응해 `layout="inline"`을 추가했다. Native는 descriptor, Web은 prop으로 전달한다. 기본 `stacked`는 유지한다. Inline은 요청 열 수와 무관하게 한 열로 배치하며 라벨 24%, 간격 `spacing.sm`, 나머지 폭은 줄바꿈 가능한 값으로 사용한다. 행마다 `spacing.sm` 세로 여백과 첫 행을 제외한 구분선을 제공한다. 제품에서 이름-값 배치를 복제하지 않도록 두 renderer가 같은 구조를 소유한다.
|
package/docs/design-profile.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 디자인 프리셋 계약
|
|
2
2
|
|
|
3
|
-
검토일: 2026-10-
|
|
3
|
+
검토일: 2026-10-17 · 상태: 기본 10종 프로필 1.15.0 · 후속 글자/질감/토큰 소비 개선 1.16.0
|
|
4
4
|
|
|
5
5
|
사용자가 레트로·종이·숲 등의 테마에 따라 같은 기능의 상호작용·구성·화면 배치도 자동으로 달라지고, 앱이 자기 테마를 한 번 주입하기를 요청했다. 색상 프리셋만으로는 그 요구를 충족하지 못하므로 네 축을 하나의 데이터 계약으로 둔다. 기존 상태 엔진을 테마마다 복제하는 방식은 채택하지 않는다.
|
|
6
6
|
|
|
@@ -47,6 +47,32 @@ export const productDesign = defineHjmDesignProfile({
|
|
|
47
47
|
|
|
48
48
|
상속 후 데이터는 재귀적으로 동결한다. 호출자의 배열/descriptor를 동결하지 않고 복사해 앱 소유 상태에 영향을 주지 않는다. light/dark 팔레트와 nested 토큰은 역할별로 병합하며, preset 원본은 바뀌지 않는다. 고정된 원·pill 의미 때문에 radius.full=999는 유지한다. 글자 크기·줄 높이·그림자·질감 범위와 지원하는 변형 이름을 검사하고 지정 색상 쌍의 대비 미달을 거부한다. 이 검사는 완성 화면 접근성 인증이 아니다.
|
|
49
49
|
|
|
50
|
+
## 미니멀·에디토리얼·터미널의 구분 — 2026-10-17
|
|
51
|
+
|
|
52
|
+
| 프리셋 | 팔레트 | 서체·제목 | 깊이·모서리 | 구성 |
|
|
53
|
+
| --- | --- | --- | --- | --- |
|
|
54
|
+
| minimal | 흰 바탕·무채색 잉크, hairline `border` #e6e6e6, 짙은 회색 행동(#3d3d3d) | ui 유지, heading·level1/2 굵기 500, body 행간 26 | raised·floating 그림자 0(오버레이는 테두리와 scrim), 4/8/12/16 | cards(테두리·안쪽 24)/inline·dashboard |
|
|
55
|
+
| editorial | 따뜻한 종이(#fdfbf7)·잉크(#1b1714), 와인 강조(#7a1f3d), 규칙선용 짙은 `border` #cfc5b8 | display·reading 시스템 serif stack, level1/2/3 56/42/30, body 행간 26 | raised 그림자 0, 0/2/2/4 | rows(규칙선)/collapsible·editorial |
|
|
56
|
+
| terminal | 밝은 모드 녹회색(#c8d4c4)·짙은 녹색 잉크·호박갈색 강조, 어두운 모드 검정(#050a06)·녹색 형광 글자·호박색 강조 | ui=code이므로 display·reading도 monospace | 그림자 0, 모서리 0 | rows(규칙선)/collapsible·dashboard |
|
|
57
|
+
|
|
58
|
+
serif stack은 `ui-serif, Iowan Old Style, Georgia, AppleMyungjo, Batang, Noto Serif KR, serif`이며 폰트를 내려받지 않는다.
|
|
59
|
+
Safari는 `ui-serif`를 New York으로, Chrome은 다음 이름부터 쓴다. 한글은 macOS AppleMyungjo·Windows Batang 등
|
|
60
|
+
설치된 serif를 쓰고 없으면 host 글꼴로 대체된다. Native는 첫 이름 `ui-serif`/`serif`를 iOS `Georgia`, 다른 host `serif`로
|
|
61
|
+
번역한다(Android는 시스템 serif를 generic 이름으로만 제공). Native의 한글 serif와 실제 기기 표시는 확인하지 않았다.
|
|
62
|
+
|
|
63
|
+
터미널의 밝은 모드는 검정 콘솔로 만들 수 없다. Notice·상태 문구의 `ACCENTS.light` 잉크는 프로필 팔레트가 바꾸지 않는
|
|
64
|
+
고정 짙은 색이라, 밝은 모드 바탕을 어둡게 하면 팔레트 대비 검사는 통과해도 이 글자가 읽히지 않는다. 그래서 그 잉크가
|
|
65
|
+
4.5:1을 유지하는 가장 어두운 녹회색(bg 약 4.6, surface 약 5.0)을 골랐다. 이 쌍은 계약 테스트가 확인한다. 강제 어두운 표현이
|
|
66
|
+
필요하면 별도 계약(프로필의 색 모드 지정)이 필요하며 이번 변경에 포함하지 않았다.
|
|
67
|
+
|
|
68
|
+
rows 구성은 테두리 없는 항목을 규칙선으로 나눈다. 이전의 작은 테두리 상자 목록은 cards와 구분되지 않았고 에디토리얼의
|
|
69
|
+
규칙선을 표현할 수 없었다. 중립·종이도 rows이므로 같은 규칙선 목록으로 바뀐다. [목록 화면 배치](usage/components/overview-screen.md#배치)를 따른다.
|
|
70
|
+
|
|
71
|
+
### 근거
|
|
72
|
+
|
|
73
|
+
- 2026-10-17 사용자 검토: 밝은 모드에서 미니멀·에디토리얼·터미널이 모두 거의 흰 화면이었고 터미널은 글꼴만 달랐다.
|
|
74
|
+
색만 바꾸지 않고 기존 팔레트·서체 역할·그림자·모서리·구성 축을 함께 조정해 정체성을 구분했다. 대비 기준은 낮추지 않았다.
|
|
75
|
+
|
|
50
76
|
## 기존 API 비교와 연결 순서
|
|
51
77
|
|
|
52
78
|
- 기존 Provider/brandPalette/environment는 유지한다. 프리셋은 별도 환경 축이 아니라 네 단계의 표현/배치 기본값이며 명시적인 props가 우선한다.
|
|
@@ -80,7 +106,7 @@ SegmentedControl·Tabs, ScreenLayout 및 optional OverviewScreen에 연결한다
|
|
|
80
106
|
`tokens.heading`은 `level1`~`level5`의 fontSize/lineHeight/fontWeight를 부분 지정한다.
|
|
81
107
|
현재 Heading은 두 renderer 모두 이 값으로 그리고 문서 `semanticLevel`과 textScale을
|
|
82
108
|
따로 유지한다. 중립은 foundation의 40/32/24/20/18px를 그대로 쓰며, 에디토리얼의
|
|
83
|
-
level1/2
|
|
109
|
+
level1/2/3은 56/42/30px·행간 66/52/40px·굵기 500(2026-10-17 44/34에서 상향), 브루탈리즘은 48/38px·행간 56/46px·굵기
|
|
84
110
|
800이다. 이 두 큰 제목 선택은 원본 치수 복제가 아니라 편집형/강한 강조 프리셋의
|
|
85
111
|
시각 계층을 구분한 HJM 실험값이며 좁은 폭·큰 글자 QA와 함께 판단한다.
|
|
86
112
|
|
package/docs/font-roles.md
CHANGED
|
@@ -23,7 +23,7 @@ body/bodyLarge는 reading, caption/label은 ui다. `fontRole` 명시값은 크
|
|
|
23
23
|
Web은 nearest Provider가 CSS stack 변수를 내보내며 semantic h1~h6·Text가 소비한다.
|
|
24
24
|
portal도 기존 Provider 복사 경로를 따라간다. Native는 View에 글꼴을 주어 전파할 수 없으므로
|
|
25
25
|
기존 Text/TextInput host와 `resolveNativeFontStyle`을 사용한다. 제목·본문은 역할 stack의 첫 named font,
|
|
26
|
-
code의 기본 monospace는 iOS Menlo/다른 host monospace로 번역한다. ui 기본 stack은 OS 기본을 유지한다.
|
|
26
|
+
code의 기본 monospace는 iOS Menlo/다른 host monospace로 번역한다. 첫 이름이 generic serif(`ui-serif`/`serif`)이면 iOS Georgia/다른 host `serif`로 번역한다(2026-10-17 에디토리얼 프리셋의 시스템 serif; Android는 시스템 serif를 generic 이름으로만 제공한다). ui 기본 stack은 OS 기본을 유지한다.
|
|
27
27
|
중첩 neutral Provider는 부모의 서체 역할도 중립으로 되돌린다.
|
|
28
28
|
|
|
29
29
|
Web stack과 Native 단일 이름은 같은 설치 지원을 뜻하지 않는다. 폰트 파일·등록·다운로드·라이선스·
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# Component maturity and evidence manifest
|
|
2
2
|
|
|
3
|
-
> Generated from `@hjmds/design-contracts` 1.
|
|
3
|
+
> Generated from `@hjmds/design-contracts` 1.27.0. Do not edit this file directly; run `pnpm contracts:sync`.
|
|
4
4
|
|
|
5
5
|
This document is the human-readable projection of the same catalog and Showcase manifest consumed by product CI.
|
|
6
6
|
|
|
7
|
-
- Contract: stable 103 · beta
|
|
8
|
-
- Web renderer: stable 103 · beta
|
|
9
|
-
- Native renderer: stable 83 · beta
|
|
7
|
+
- Contract: stable 103 · beta 2
|
|
8
|
+
- Web renderer: stable 103 · beta 2
|
|
9
|
+
- Native renderer: stable 83 · beta 4 · unsupported 18
|
|
10
10
|
|
|
11
11
|
| Component | Canonical story ID | Contract | Web | Native | Documentation | Required evidence |
|
|
12
12
|
| --- | --- | --- | --- | --- | --- | --- |
|
|
@@ -43,6 +43,7 @@ This document is the human-readable projection of the same catalog and Showcase
|
|
|
43
43
|
| RadioGroup | `input/radio-group` | stable | stable | stable | generated only | contract: contract; web: default, dark, long-copy, large-text, rtl, reduced-motion, accessibility, keyboard; native: default, dark, long-copy, large-text, rtl, reduced-motion, accessibility, native-actions |
|
|
44
44
|
| Switch | `input/switch` | stable | stable | stable | generated only | contract: contract; web: default, dark, long-copy, large-text, rtl, reduced-motion, accessibility, keyboard; native: default, dark, long-copy, large-text, rtl, reduced-motion, accessibility, native-actions |
|
|
45
45
|
| Chip | `input/chip` | stable | stable | stable | generated only | contract: contract; web: default, dark, long-copy, large-text, rtl, reduced-motion, accessibility, keyboard; native: default, dark, long-copy, large-text, rtl, reduced-motion, accessibility, native-actions |
|
|
46
|
+
| ImageChoiceGroup | `input/image-choice-group` | beta | beta | beta | generated only | contract: contract; web: default, dark, long-copy, large-text, rtl, reduced-motion, accessibility; native: default, dark, long-copy, large-text, rtl, reduced-motion, accessibility |
|
|
46
47
|
| SegmentedControl | `input/segmented-control` | stable | stable | stable | generated only | contract: contract; web: default, dark, long-copy, large-text, rtl, reduced-motion, accessibility, keyboard; native: default, dark, long-copy, large-text, rtl, reduced-motion, accessibility, native-actions |
|
|
47
48
|
| ToggleGroup | `input/toggle-group` | stable | stable | stable | [authored](../toggle-group.md) | contract: contract; web: default, dark, long-copy, large-text, rtl, reduced-motion, accessibility, keyboard; native: default, dark, long-copy, large-text, rtl, reduced-motion, accessibility, native-actions |
|
|
48
49
|
| TagsInput | `input/tags-input` | stable | stable | stable | [authored](../tags-input.md) | contract: contract; web: default, dark, long-copy, large-text, rtl, reduced-motion, accessibility, keyboard; native: default, dark, long-copy, large-text, rtl, reduced-motion, accessibility, native-actions |
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"designSystemVersion": "1.
|
|
3
|
+
"designSystemVersion": "1.27.0",
|
|
4
4
|
"source": "packages/design-contracts/docs/generated/showcase-manifest.json",
|
|
5
5
|
"surfaces": {
|
|
6
6
|
"web": {
|
|
7
7
|
"packageName": "@hjmds/react",
|
|
8
|
-
"packageVersion": "1.
|
|
9
|
-
"activeComponents":
|
|
8
|
+
"packageVersion": "1.27.0",
|
|
9
|
+
"activeComponents": 105,
|
|
10
10
|
"claimedComponents": 103,
|
|
11
11
|
"completeScenarioComponents": 103,
|
|
12
12
|
"components": [
|
|
@@ -1778,6 +1778,34 @@
|
|
|
1778
1778
|
],
|
|
1779
1779
|
"missingScenarios": []
|
|
1780
1780
|
},
|
|
1781
|
+
{
|
|
1782
|
+
"componentId": "image-choice-group",
|
|
1783
|
+
"name": "ImageChoiceGroup",
|
|
1784
|
+
"status": "beta",
|
|
1785
|
+
"claimed": false,
|
|
1786
|
+
"subpath": null,
|
|
1787
|
+
"exportNames": [],
|
|
1788
|
+
"proofs": [],
|
|
1789
|
+
"requiredScenarios": [
|
|
1790
|
+
"default",
|
|
1791
|
+
"dark",
|
|
1792
|
+
"long-copy",
|
|
1793
|
+
"large-text",
|
|
1794
|
+
"rtl",
|
|
1795
|
+
"reduced-motion",
|
|
1796
|
+
"accessibility"
|
|
1797
|
+
],
|
|
1798
|
+
"claimedScenarios": [],
|
|
1799
|
+
"missingScenarios": [
|
|
1800
|
+
"default",
|
|
1801
|
+
"dark",
|
|
1802
|
+
"long-copy",
|
|
1803
|
+
"large-text",
|
|
1804
|
+
"rtl",
|
|
1805
|
+
"reduced-motion",
|
|
1806
|
+
"accessibility"
|
|
1807
|
+
]
|
|
1808
|
+
},
|
|
1781
1809
|
{
|
|
1782
1810
|
"componentId": "segmented-control",
|
|
1783
1811
|
"name": "SegmentedControl",
|
|
@@ -5672,9 +5700,9 @@
|
|
|
5672
5700
|
},
|
|
5673
5701
|
"native": {
|
|
5674
5702
|
"packageName": "@hjmds/react-native",
|
|
5675
|
-
"packageVersion": "1.
|
|
5676
|
-
"activeComponents":
|
|
5677
|
-
"claimedComponents":
|
|
5703
|
+
"packageVersion": "1.27.0",
|
|
5704
|
+
"activeComponents": 87,
|
|
5705
|
+
"claimedComponents": 84,
|
|
5678
5706
|
"completeScenarioComponents": 83,
|
|
5679
5707
|
"components": [
|
|
5680
5708
|
{
|
|
@@ -7326,6 +7354,64 @@
|
|
|
7326
7354
|
],
|
|
7327
7355
|
"missingScenarios": []
|
|
7328
7356
|
},
|
|
7357
|
+
{
|
|
7358
|
+
"componentId": "image-choice-group",
|
|
7359
|
+
"name": "ImageChoiceGroup",
|
|
7360
|
+
"status": "beta",
|
|
7361
|
+
"claimed": true,
|
|
7362
|
+
"subpath": "./image-choice",
|
|
7363
|
+
"exportNames": [
|
|
7364
|
+
"ImageChoiceGroup"
|
|
7365
|
+
],
|
|
7366
|
+
"proofs": [
|
|
7367
|
+
{
|
|
7368
|
+
"scenarios": [
|
|
7369
|
+
"default"
|
|
7370
|
+
],
|
|
7371
|
+
"file": "test/default-render.test.tsx",
|
|
7372
|
+
"caseId": "image-choice-group"
|
|
7373
|
+
},
|
|
7374
|
+
{
|
|
7375
|
+
"scenarios": [
|
|
7376
|
+
"accessibility",
|
|
7377
|
+
"dark",
|
|
7378
|
+
"large-text",
|
|
7379
|
+
"rtl",
|
|
7380
|
+
"reduced-motion"
|
|
7381
|
+
],
|
|
7382
|
+
"file": "test/scenario-matrix.test.tsx",
|
|
7383
|
+
"caseId": "image-choice-group"
|
|
7384
|
+
},
|
|
7385
|
+
{
|
|
7386
|
+
"scenarios": [
|
|
7387
|
+
"native-actions"
|
|
7388
|
+
],
|
|
7389
|
+
"file": "test/image-choice.test.tsx",
|
|
7390
|
+
"caseId": "image-choice-group"
|
|
7391
|
+
}
|
|
7392
|
+
],
|
|
7393
|
+
"requiredScenarios": [
|
|
7394
|
+
"default",
|
|
7395
|
+
"dark",
|
|
7396
|
+
"long-copy",
|
|
7397
|
+
"large-text",
|
|
7398
|
+
"rtl",
|
|
7399
|
+
"reduced-motion",
|
|
7400
|
+
"accessibility"
|
|
7401
|
+
],
|
|
7402
|
+
"claimedScenarios": [
|
|
7403
|
+
"default",
|
|
7404
|
+
"accessibility",
|
|
7405
|
+
"dark",
|
|
7406
|
+
"large-text",
|
|
7407
|
+
"rtl",
|
|
7408
|
+
"reduced-motion",
|
|
7409
|
+
"native-actions"
|
|
7410
|
+
],
|
|
7411
|
+
"missingScenarios": [
|
|
7412
|
+
"long-copy"
|
|
7413
|
+
]
|
|
7414
|
+
},
|
|
7329
7415
|
{
|
|
7330
7416
|
"componentId": "segmented-control",
|
|
7331
7417
|
"name": "SegmentedControl",
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# Renderer evidence coverage
|
|
2
2
|
|
|
3
|
-
> Generated for HJM 1.
|
|
3
|
+
> Generated for HJM 1.27.0. Do not edit directly; run `pnpm evidence:sync`.
|
|
4
4
|
|
|
5
5
|
This projection joins the canonical surface maturity manifest with first-party renderer claims. Missing scenarios are explicit beta promotion debt; stable surfaces are blocked by CI until none remain.
|
|
6
6
|
|
|
7
|
-
- web: 103/
|
|
8
|
-
- native:
|
|
7
|
+
- web: 103/105 active implementations; 103/105 required scenario sets
|
|
8
|
+
- native: 84/87 active implementations; 83/87 required scenario sets
|
|
9
9
|
|
|
10
10
|
| Component | Surface | Maturity | Renderer package | Export | Claimed scenarios | Missing required scenarios | Executable proofs |
|
|
11
11
|
| --- | --- | --- | --- | --- | --- | --- | --- |
|
|
@@ -42,6 +42,7 @@ This projection joins the canonical surface maturity manifest with first-party r
|
|
|
42
42
|
| RadioGroup | web | stable | @hjmds/react | ./selection | default, accessibility, dark, large-text, rtl, reduced-motion, long-copy, keyboard | none | test/default-render.ssr.test.tsx#radio-group, test/scenario-matrix.browser.test.tsx#radio-group, test/stable-core.browser.test.tsx#radio-group |
|
|
43
43
|
| Switch | web | stable | @hjmds/react | ./selection | default, accessibility, dark, large-text, rtl, reduced-motion, long-copy, keyboard | none | test/default-render.ssr.test.tsx#switch, test/scenario-matrix.browser.test.tsx#switch, test/stable-core.browser.test.tsx#switch |
|
|
44
44
|
| Chip | web | stable | @hjmds/react | ./selection | default, accessibility, dark, large-text, rtl, reduced-motion, long-copy, keyboard | none | test/default-render.ssr.test.tsx#chip, test/scenario-matrix.browser.test.tsx#chip, test/stable-core.browser.test.tsx#chip |
|
|
45
|
+
| ImageChoiceGroup | web | beta | @hjmds/react | unclaimed | none | default, dark, long-copy, large-text, rtl, reduced-motion, accessibility | none |
|
|
45
46
|
| SegmentedControl | web | stable | @hjmds/react | ./selection | default, accessibility, dark, large-text, rtl, reduced-motion, long-copy, keyboard | none | test/default-render.ssr.test.tsx#segmented-control, test/scenario-matrix.browser.test.tsx#segmented-control, test/stable-core.browser.test.tsx#segmented-control |
|
|
46
47
|
| ToggleGroup | web | stable | @hjmds/react | ./toggle-group | default, accessibility, dark, large-text, rtl, reduced-motion, long-copy, keyboard | none | test/default-render.ssr.test.tsx#toggle-group, test/scenario-matrix.browser.test.tsx#toggle-group, test/stable-core.browser.test.tsx#toggle-group |
|
|
47
48
|
| TagsInput | web | stable | @hjmds/react | ./tags-input | default, accessibility, dark, large-text, rtl, reduced-motion, long-copy, keyboard | none | test/default-render.ssr.test.tsx#tags-input, test/scenario-matrix.browser.test.tsx#tags-input, test/stable-core.browser.test.tsx#tags-input |
|
|
@@ -144,6 +145,7 @@ This projection joins the canonical surface maturity manifest with first-party r
|
|
|
144
145
|
| RadioGroup | native | stable | @hjmds/react-native | ./inputs | default, accessibility, dark, large-text, rtl, reduced-motion, long-copy, native-actions | none | test/default-render.test.tsx#radio-group, test/scenario-matrix.test.tsx#radio-group, test/stable-core.test.tsx#radio-group |
|
|
145
146
|
| Switch | native | stable | @hjmds/react-native | ./inputs | default, accessibility, dark, large-text, rtl, reduced-motion, long-copy, native-actions | none | test/default-render.test.tsx#switch, test/scenario-matrix.test.tsx#switch, test/stable-core.test.tsx#switch |
|
|
146
147
|
| Chip | native | stable | @hjmds/react-native | ./inputs | default, accessibility, dark, large-text, rtl, reduced-motion, long-copy, native-actions | none | test/default-render.test.tsx#chip, test/scenario-matrix.test.tsx#chip, test/stable-core.test.tsx#chip |
|
|
148
|
+
| ImageChoiceGroup | native | beta | @hjmds/react-native | ./image-choice | default, accessibility, dark, large-text, rtl, reduced-motion, native-actions | long-copy | test/default-render.test.tsx#image-choice-group, test/scenario-matrix.test.tsx#image-choice-group, test/image-choice.test.tsx#image-choice-group |
|
|
147
149
|
| SegmentedControl | native | stable | @hjmds/react-native | ./inputs | default, accessibility, dark, large-text, rtl, reduced-motion, long-copy, native-actions | none | test/default-render.test.tsx#segmented-control, test/scenario-matrix.test.tsx#segmented-control, test/stable-core.test.tsx#segmented-control |
|
|
148
150
|
| ToggleGroup | native | stable | @hjmds/react-native | ./toggle-group | default, accessibility, dark, large-text, rtl, reduced-motion, long-copy, native-actions | none | test/default-render.test.tsx#toggle-group, test/scenario-matrix.test.tsx#toggle-group, test/stable-core.test.tsx#toggle-group |
|
|
149
151
|
| TagsInput | native | stable | @hjmds/react-native | ./tags-input | default, accessibility, dark, large-text, rtl, reduced-motion, long-copy, native-actions | none | test/default-render.test.tsx#tags-input, test/scenario-matrix.test.tsx#tags-input, test/stable-core.test.tsx#tags-input |
|