@hjmds/design-contracts 1.28.1 → 1.30.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/catalog.d.ts +486 -0
- package/dist/catalog.d.ts.map +1 -1
- package/dist/catalog.js +154 -105
- package/dist/catalog.js.map +1 -1
- package/dist/component-definitions.d.ts +21 -109
- package/dist/component-definitions.d.ts.map +1 -1
- package/dist/component-definitions.js +9 -109
- package/dist/component-definitions.js.map +1 -1
- 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/screen-patterns.d.ts +58 -1
- package/dist/screen-patterns.d.ts.map +1 -1
- package/dist/screen-patterns.js +31 -0
- package/dist/screen-patterns.js.map +1 -1
- package/dist/showcase.d.ts.map +1 -1
- package/dist/showcase.js +7 -0
- package/dist/showcase.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/architecture.md +18 -0
- package/docs/generated/component-maturity.md +29 -7
- package/docs/generated/renderer-evidence.json +4056 -1741
- package/docs/generated/renderer-evidence.md +237 -193
- package/docs/generated/showcase-manifest.json +1525 -6
- package/docs/screen-patterns.md +8 -1
- package/docs/stable-core.md +22 -0
- package/docs/usage/README.md +24 -24
- package/docs/usage/SELECTION.md +1 -1
- package/docs/usage/components/auth-screen-layout.md +1 -0
- package/docs/usage/components/dialog.md +1 -1
- package/docs/usage/components/editor-screen.md +1 -1
- package/docs/usage/components/field.md +1 -1
- package/docs/usage/components/icon-button.md +1 -0
- package/docs/usage/components/screen-layout.md +7 -3
- package/docs/usage/components/search-field.md +1 -1
- package/docs/usage/components/sheet.md +1 -1
- package/docs/usage/components/text-area.md +1 -1
- package/package.json +2 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"screen-patterns.js","sourceRoot":"","sources":["../src/screen-patterns.ts"],"names":[],"mappings":"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","sourcesContent":["import { glyph, layout, radius, spacing } from \"./foundations.js\";\nimport { avatarRecipe } from \"./component-recipes.js\";\nimport type { MenuItemDescriptor } from \"./behaviors.js\";\n\n/** Initial load replaces the body; refresh/save errors belong beside retained content. */\nexport type ScreenContentState =\n | Readonly<{ kind: \"ready\" }>\n | Readonly<{ kind: \"loading\" | \"empty\" | \"error\" | \"restricted\"; title: string; description?: string }>;\n\nexport function resolveScreenContentState(state: ScreenContentState = { kind: \"ready\" }) {\n if (![\"ready\", \"loading\", \"empty\", \"error\", \"restricted\"].includes(state.kind)) {\n throw new TypeError(\"Unknown screen content state\");\n }\n if (state.kind !== \"ready\" && !state.title.trim()) {\n throw new TypeError(\"Screen state requires a localized title\");\n }\n return {\n kind: state.kind,\n replacesContent: state.kind !== \"ready\",\n busy: state.kind === \"loading\",\n announcement: state.kind === \"error\" ? \"assertive\" : \"polite\",\n } as const;\n}\n\n/**\n * Native header band heights. Titled centered headers match the iOS navigation bar (44 control + 4 + 4);\n * icon-only centered headers are compact (2026-10-14 야잘알 tab spacing, 2026-10-17 \"상단 여백 줄여\").\n * Body top padding shrinks only under a compact header without a notice.\n */\nexport const screenHeaderRecipe = {\n minHeight: 52,\n paddingVertical: spacing.xxs,\n compactMinHeight: 48,\n compactPaddingVertical: 2,\n compactBodyTop: spacing.xxs,\n /**\n * Heading levels for the route title, shared by Web and Native (2026-10-17 comparison: Native drew the\n * title as regular-weight Text — 20 start / 18 centered — while Web used bold Heading levels).\n */\n titleLevel: \"level3\",\n centeredTitleLevel: \"level5\",\n} as const;\n\n/**\n * Leaving a screen (back, close, \"설정 나가기\") is an icon-only button fixed at the header's leading edge\n * (2026-10-17 user rule: exits had drifted into body text buttons with mixed glyphs). The label is read\n * by assistive tech only. `back` mirrors in RTL; `close` is for modal-style routes.\n */\nexport type ScreenExitKind = \"back\" | \"close\";\nexport const screenExitRecipe = {\n /** Chevron arm length and stroke; close cross arm length. Drawn, not font glyphs, so every platform matches. */\n chevronSize: 10,\n closeSize: 14,\n stroke: 2,\n} as const;\nexport function validateScreenExit(exit: Readonly<{ kind: string; label: string }>, hasLeading: boolean) {\n if (exit.kind !== \"back\" && exit.kind !== \"close\") throw new TypeError(\"Screen exit kind must be back or close\");\n if (!exit.label.trim()) throw new TypeError(\"Screen exit needs a localized accessible label\");\n if (hasLeading) throw new TypeError(\"Screen exit owns the leading slot; do not also pass leading\");\n}\n\n/**\n * Who owns the screen gutters. `default`: the shared shell pads header, notice, body and footer. `none`: the host\n * route already insets everything (≈45 product call sites rely on this meaning, so it cannot change).\n * `body-edge`: header, notice and footer keep the shell padding; only the body's inline padding is 0 so full-width\n * list rows (ConversationRow, ListRow-based items) supply their own inset — review S5#9 measured DM avatars ~32pt\n * from the edge because body padding and row padding stacked (2026-10-17 user decision).\n */\nexport type ScreenContentInset = \"default\" | \"none\" | \"body-edge\";\nexport const screenContentInsets = [\"default\", \"none\", \"body-edge\"] as const satisfies readonly ScreenContentInset[];\n\n/**\n * 화면 진입 시 첫 입력 포커스(2026-10-18 사용자 요청: \"input이 있는 화면에 진입하면 포커스되도록, 웹앱 둘 다\").\n * 앱마다 autoFocus를 따로 붙이던 일을 화면 골격이 맡는다. 입력 칸은 가장 가까운 화면·시트 범위에 자신을 등록하고,\n * 범위가 진입이 끝난 뒤(Native: 전환·애니메이션 interaction 뒤, Web: mount 직후) 아래 규칙으로 한 번 고른다.\n *\n * - `first-input`: `initialFocusTarget`을 준 칸이 있으면 그 칸, 없으면 등록 순서상 첫 칸. 입력이 화면의 주 행동인 구성\n * (검색, 작성·편집)의 기본값이다.\n * - `single-input`: 등록된 텍스트 입력이 정확히 하나일 때만 그 칸. 시트·대화상자의 기본값이다 — 칸이 여럿이면 어느\n * 것이 주인지 알 수 없어 기존 포커스 규칙(첫 포커스 가능 요소·덜 파괴적인 행동)을 그대로 둔다.\n * - `none`: 고르지 않는다. 일반 화면과, 입력이 읽기의 보조인 대화·댓글 화면의 기본값이다 — 키보드가 올라오면 읽던\n * 기록을 가린다. 같은 prop으로 켤 수 있다.\n *\n * 비활성·읽기 전용 칸은 고르지 않고 `initialFocusTarget={false}` 칸은 제외한다. 화면 범위는 mount당 한 번만 포커스한다:\n * 스택에서 돌아온 화면(이미 mount된 화면)을 다시 포커스하면 키보드가 돌아온 맥락을 가리고, HJM은 내비게이션 포커스\n * 신호를 알지 못한다. 시트·대화상자는 열릴 때마다 다시 고른다. 모션 감소는 애니메이션에만 적용하고 포커스는 그대로 한다.\n */\nexport type InitialFocusMode = \"first-input\" | \"single-input\" | \"none\";\nexport type ScreenInitialFocus = \"first-input\" | \"none\";\nexport type InitialFocusCandidate = Readonly<{\n /** Registration order inside the scope (tree order). */\n order: number;\n /** `initialFocusTarget` on the field: true prefers it, false excludes it, undefined keeps it eligible. */\n preference: boolean | undefined;\n /** False for disabled or read-only fields at resolve time. */\n focusable: boolean;\n}>;\n\n/** Defaults per composition; renderers read these instead of repeating literals. */\nexport const initialFocusDefaults = {\n screen: \"none\",\n search: \"first-input\",\n editor: \"first-input\",\n chat: \"none\",\n commentThread: \"none\",\n overlay: \"single-input\",\n} as const satisfies Record<string, InitialFocusMode>;\n\nexport function resolveInitialFocusTarget<T extends InitialFocusCandidate>(candidates: readonly T[], mode: InitialFocusMode): T | null {\n if (mode === \"none\") return null;\n const ordered = [...candidates].sort((a, b) => a.order - b.order);\n if (mode === \"single-input\") {\n const only = ordered.length === 1 ? ordered[0]! : null;\n return only && only.focusable && only.preference !== false ? only : null;\n }\n const eligible = ordered.filter(candidate => candidate.focusable && candidate.preference !== false);\n return eligible.find(candidate => candidate.preference === true) ?? eligible[0] ?? null;\n}\n\n// Reuse reading-width and spacing tokens; do not derive geometry from a product's device or artwork.\nexport const screenPatternRecipe = {\n maxWidth: layout.readingMaxWidth,\n padding: spacing.md,\n sectionGap: spacing.xl,\n itemGap: spacing.sm,\n stateGap: spacing.md,\n // Compact screens must keep back/title/save on one row; scale this floor for large text instead of reserving a desktop-width title.\n headerMinWidth: layout.readingMaxWidth / 6,\n // Reserve the opposite edge for authorship and cap the composer so history remains visible.\n messageMaxWidth: \"84%\",\n // Social thumbnails stay compact; selection order and removal replace a second toolbar.\n attachmentSize: 80,\n attachmentRemoveSize: 24,\n reactionHoldMs: 450,\n reactionMoveTolerance: 10,\n reactionMenuWidth: 320,\n replySwipeDistance: 60,\n composerMinLines: 1,\n composerMaxLines: 5,\n} as const;\n\n/** Controlled composer: HJM never clears drafts or interprets a fulfilled callback as server delivery. */\nexport type MessageComposerDescriptor = Readonly<{\n value: string;\n label: string;\n sendLabel: string;\n /** Short visual copy may differ from the complete accessible input name. */\n placeholder?: string;\n description?: string;\n error?: string;\n invalid?: boolean;\n /** Newline remains the compatible default; desktop chat may explicitly opt into send. */\n submitMode?: \"newline\" | \"send\";\n disabled?: boolean;\n pending?: boolean;\n attachmentCount?: number;\n}>;\n/** Safari may report the final IME Enter as keyCode 229 after isComposing becomes false. */\nexport function shouldSubmitMessageKey(event: Readonly<{ key: string; shiftKey?: boolean; isComposing?: boolean; keyCode?: number }>, mode: \"newline\" | \"send\" = \"newline\"): boolean {\n return mode === \"send\" && event.key === \"Enter\" && !event.shiftKey && !event.isComposing && event.keyCode !== 229;\n}\nexport function canSubmitMessage({ value, disabled = false, pending = false, attachmentCount = 0 }: MessageComposerDescriptor): boolean {\n if (!Number.isSafeInteger(attachmentCount) || attachmentCount < 0) throw new RangeError(\"Attachment count must be a nonnegative integer\");\n return !disabled && !pending && (value.trim().length > 0 || attachmentCount > 0);\n}\n\n/**\n * Shared timeline geometry. 2026-10-16 user decision: the common chat standard follows the measured\n * KakaoTalk iOS chat room (@3x capture: bubble ~35pt tall, radius ~14, run gap ~6, group gap ~12,\n * avatar ~34, avatar gap 8). Brand colors and artwork are not copied; surfaces stay semantic tokens.\n */\nexport const chatMessageRecipe = {\n // Must be a size the Avatar renders on both platforms: 36 was no Web Avatar step (32/40/48/64), so Web drew a 32\n // avatar in a 36 slot while Native drew 36 (2026-10-17 measured audit). `small` is the step nearest the ~34 reference.\n avatarSize: avatarRecipe.sizes.small,\n avatarGap: spacing.xs,\n authorGap: spacing.xxs,\n metaGap: spacing.xxs,\n bubbleRadius: 14,\n bubblePaddingInline: 10,\n bubblePaddingBlock: 6,\n // Bubbles of one run read as a stack; a new author or minute starts a visibly separate group.\n runGap: 6,\n groupGap: spacing.sm,\n // Flat-topped tip continuing the bubble's top edge; the tipped corner tightens to meet it.\n tailWidth: 7,\n tailHeight: 10,\n tailCornerRadius: 4,\n jumpToLatestGap: spacing.xs,\n // Timeline side gutter (measured 10pt); header and composer keep the screen padding.\n timelineInset: 10,\n // Photos render without the bubble surface (measured reference: ~210pt wide, bubble radius).\n mediaWidth: 210,\n mediaGap: 2,\n} as const;\n\n/** Column count for a photo set: pairs read as 2-up, other counts as 3-up; one photo spans the width. */\nexport function resolveChatMediaColumns(count: number): 1 | 2 | 3 {\n if (!Number.isSafeInteger(count) || count < 1) throw new RangeError(\"Chat media requires at least one item\");\n return count === 1 ? 1 : count === 2 || count === 4 ? 2 : 3;\n}\n\n/**\n * Long-press menu geometry measured from the Instagram iOS DM hold menu (2026-10-16 @3x capture):\n * full-width reaction strip ~60pt with ~30pt emoji, the pressed bubble itself as preview, and a ~200pt\n * action card aligned to the bubble's side with ~56pt rows. 12pt between the three blocks.\n */\n/** Emoji row above a comment composer (Instagram comment sheet, 2026-10-16): evenly spread 44pt targets. */\nexport const composerQuickInsertRecipe = { itemSize: 44, emojiSize: 26, gap: spacing.xs } as const;\n\nexport const holdMenuRecipe = {\n inset: 10,\n gap: spacing.sm,\n stripHeight: 60,\n stripItemSize: 48,\n emojiSize: 28,\n actionWidth: 200,\n actionRowHeight: 56,\n actionRadius: 18,\n iconSize: 24,\n} as const;\n\n/** Position inside a run of consecutive messages from one author within one displayed minute. */\nexport type ChatMessageGroupPosition = \"single\" | \"first\" | \"middle\" | \"last\";\n\n/**\n * Runs break when the author or the displayed timestamp changes, so each minute shows its time once\n * and a new minute re-introduces the author (KakaoTalk behavior). Products pass the same localized\n * timestamp string they render; HJM never parses dates.\n */\nexport function resolveChatMessageGroups(items: readonly Readonly<{ id: string; authorId: string; timestamp: string }>[]): ReadonlyMap<string, ChatMessageGroupPosition> {\n const positions = new Map<string, ChatMessageGroupPosition>();\n items.forEach((item, index) => {\n if (!item.id.trim() || positions.has(item.id)) throw new TypeError(\"Chat messages require unique, nonempty ids\");\n const same = (other: (typeof items)[number] | undefined) => !!other && other.authorId === item.authorId && other.timestamp === item.timestamp;\n const before = same(items[index - 1]), after = same(items[index + 1]);\n positions.set(item.id, before ? (after ? \"middle\" : \"last\") : after ? \"first\" : \"single\");\n });\n return positions;\n}\n\n/** What one bubble shows for its run position; both renderers read this instead of re-deriving rules. */\nexport function resolveChatMessageGroupDisplay(position: ChatMessageGroupPosition = \"single\") {\n if (![\"single\", \"first\", \"middle\", \"last\"].includes(position)) throw new TypeError(\"Unknown chat message group position\");\n const starts = position === \"single\" || position === \"first\";\n const ends = position === \"single\" || position === \"last\";\n return { showAuthor: starts, showAvatar: starts, showTail: starts, showTimestamp: ends, spacingBefore: starts ? chatMessageRecipe.groupGap : chatMessageRecipe.runGap } as const;\n}\n\n/** Bubble alignment expresses authorship, not delivery; delivery text always comes from the product receipt. */\nexport type ChatMessageDescriptor = Readonly<{\n direction: \"incoming\" | \"outgoing\";\n author: string;\n timestamp: string;\n deliveryLabel?: string;\n /** Inward drag reveals time (incoming right, outgoing left) while delivery state remains visible; default shows time beside the last bubble of a run. */\n timestampPresentation?: \"always\" | \"swipe\";\n /** Authorship tip on the run's first bubble. Default on since the 2026-10-16 timeline standard. */\n bubbleTail?: boolean;\n /** From resolveChatMessageGroups; omitted means a standalone message. */\n groupPosition?: ChatMessageGroupPosition;\n}>;\n\n/** A denied permission goes to settings; rendering never requests OS access automatically. */\nexport type PermissionScreenStatus = \"prompt\" | \"denied\" | \"granted\" | \"unavailable\";\nexport function resolvePermissionAction(status:PermissionScreenStatus) {\n switch(status){case \"prompt\":return \"request\";case \"denied\":return \"settings\";case \"granted\":return \"continue\";case \"unavailable\":return null;default:throw new TypeError(\"Unknown permission state\");}\n}\nexport function resolveOnboardingStep(total:number,index:number){\n if(!Number.isInteger(total)||total<1||!Number.isInteger(index)||index<0||index>=total)throw new RangeError(\"Onboarding requires a valid step index\");\n return {first:index===0,last:index===total-1};\n}\n\n/**\n * Shared comment-row geometry. 2026-10-16 user decision: comments follow the measured Instagram iOS\n * comment sheet (@3x capture: avatar 32 / reply 24, avatar gap 8, like count under the heart,\n * \"Reply\" as quiet text below the body, replies indented to the text column). Artwork is not copied.\n */\nexport const commentThreadRecipe = {\n avatarSize: 32,\n replyAvatarSize: 24,\n avatarGap: spacing.xs,\n lineGap: 2,\n rowGap: spacing.sm,\n // Replies align with the parent's text column instead of an arbitrary section inset.\n replyIndent: 32 + spacing.xs,\n // The heart keeps the 44pt touch target even though the measured reference draws a smaller glyph.\n likeColumnWidth: 44,\n // Optional photo/sticker under the body; the measured reference keeps it thumbnail-sized.\n mediaMaxWidth: 160,\n mediaRadius: radius.md,\n // The trailing vertical-dots menu glyph; the button keeps the shared 44pt IconButton target.\n menuGlyphSize: glyph.sm,\n /**\n * Trailing actions (like, product actions, more) centre their 44 targets on the identity's first line instead of\n * top-aligning the target box (2026-10-17 measured audit: avatar 168 / author line 162 / glyphs 174). The cluster\n * shifts by (first-line height − visible target) / 2 — negative while the line is shorter than the target — and the\n * last control takes IconButton `edge=\"end\"` so its glyph slot ends on the row inset like the avatar starts on it.\n * The first line is the author caption, or the body line when the author runs inline with `bodyText`.\n */\n actionAnchor: { authorTextVariant: \"caption\", inlineTextVariant: \"body\" },\n} as const;\n\n/**\n * Items of the HJM-owned per-comment \"more\" menu (2026-10-17: message/comment structure belongs to HJM, review S4#7).\n * Same vocabulary as Menu/ContextMenu; the product supplies only ids, localized labels, tone and availability.\n */\nexport type CommentMenuItemDescriptor<Key extends string = string> = Pick<MenuItemDescriptor<Key>, \"id\" | \"label\" | \"disabled\" | \"tone\">;\n/** Danger actions (delete, block) always sit last so a destructive row is never the first target; order is otherwise kept. */\nexport function resolveCommentMenuItems<Key extends string>(items: readonly CommentMenuItemDescriptor<Key>[]): readonly CommentMenuItemDescriptor<Key>[] {\n const ids = new Set<string>();\n for (const item of items) {\n if (!item.id.trim() || ids.has(item.id) || !item.label.trim()) throw new TypeError(\"Comment menu items require unique ids and localized labels\");\n ids.add(item.id);\n }\n return [...items.filter(item => item.tone !== \"danger\"), ...items.filter(item => item.tone === \"danger\")];\n}\n\n/** Replies are one level deep; reject orphaned/duplicate records instead of silently losing them. */\nexport function validateCommentThread(items:readonly {id:string;parentId:string|null}[]){\n const roots=new Set(items.filter(item=>item.parentId===null).map(item=>item.id));const ids=new Set<string>();\n for(const item of items){if(!item.id.trim()||ids.has(item.id))throw new TypeError(\"Comment ids must be unique and nonempty\");ids.add(item.id);if(item.parentId!==null&&(!roots.has(item.parentId)||item.parentId===item.id))throw new TypeError(\"Replies require an existing root comment\");}\n}\n\n/** Source bytes, permission requests, ordering and upload limits remain product-owned. */\nexport type MessageAttachmentDescriptor = Readonly<{ id: string; removeLabel: string; /** Local preparation can lock removal without locking text entry. */ disabled?: boolean }>;\nexport function validateMessageAttachments(attachments: readonly MessageAttachmentDescriptor[]): void {\n const ids = new Set<string>();\n for (const item of attachments) {\n if (!item.id.trim() || ids.has(item.id) || !item.removeLabel.trim()) throw new TypeError(\"Attachments require unique ids and localized removal labels\");\n ids.add(item.id);\n }\n}\n\n/** Require horizontal intent so a timeline scroll cannot accidentally start a reply. */\nexport function isReplySwipe(dx: number, dy: number): boolean {\n return Math.abs(dx) >= screenPatternRecipe.replySwipeDistance && Math.abs(dx) > Math.abs(dy) * 2;\n}\n\n/** The UI never infers permission or camera availability; product adapters own both. */\nexport type PhotoSource = \"library\" | \"camera\";\nexport type PhotoSourceLabels = Readonly<{ title:string; library:string; camera:string; cancel:string }>;\n\nexport type SavedItem = Readonly<{ id: string; title: string }>;\nexport type SavedCollection = Readonly<{ id: string; title: string; itemIds: readonly string[] }>;\nexport type SavedItemsLabels = Readonly<{ allItems: string; privateNotice: string; back: string; empty: string; createCollection: string }>;\n\n/** Unsave removes an item from every collection view without rewriting product-owned membership. */\nexport function resolveSavedItems<T extends SavedItem>(items:readonly T[],collections:readonly SavedCollection[],collectionId:string|null|undefined,selectedItemId:string|null|undefined){\n const ids=new Set<string>(),groups=new Set<string>();\n for(const item of items){if(!item.id.trim()||ids.has(item.id)||!item.title.trim())throw new TypeError(\"Saved items require unique ids and nonempty titles\");ids.add(item.id);}\n for(const group of collections){if(!group.id.trim()||groups.has(group.id)||!group.title.trim())throw new TypeError(\"Saved collections require unique ids and nonempty titles\");groups.add(group.id);}\n const collection=collections.find(item=>item.id===collectionId);\n // A deleted collection returns to the overview instead of showing a mislabeled all-posts view.\n const home=collectionId===undefined||(collectionId!==null&&!collection);\n const visible=home||collectionId===null?items:items.filter(item=>collection?.itemIds.includes(item.id));\n return {home,collection,visible,selected:home?undefined:visible.find(item=>item.id===selectedItemId)};\n}\n\n/**\n * SearchScreen phases (2026-10-06 search redesign, docs/screen-patterns.md#searchscreen-두-단계-검색).\n * Without a committed query (one-step search, the pre-1.13 behavior) any nonblank query is already\n * `results`. With one, typing a different query is `typing`: suggestions replace the results until the\n * user commits (Enter, a suggestion, a recent or suggested query). Comparing trimmed values keeps a\n * trailing space from flipping committed results back into suggestions.\n */\nexport type SearchScreenPhase = \"idle\" | \"typing\" | \"results\";\nexport function resolveSearchScreenPhase(query: string, committedQuery?: string): SearchScreenPhase {\n const typed = query.trim();\n if (!typed) return \"idle\";\n if (committedQuery === undefined) return \"results\";\n return typed === committedQuery.trim() ? \"results\" : \"typing\";\n}\n\n/**\n * The value a commit records, or `null` when there is nothing to commit. Blank commits are dropped\n * so a stray Enter never writes an empty recent search or fetches \"everything\".\n */\nexport function resolveSearchCommit(value: string): string | null {\n const next = value.trim();\n return next ? next : null;\n}\n\n/**\n * Why a committed search shows nothing. `filters` keeps the filter rail and offers \"clear all\";\n * `query` hides the rail (no filter can fix it) and offers suggested queries instead. Reference\n * services hide the rail on every zero result, which removes the only way to undo a filter.\n * `null` count means the result is still loading, so no cause is reported yet.\n */\nexport type SearchEmptyCause = \"none\" | \"filters\" | \"query\";\nexport function resolveSearchEmptyCause(count: number | null, appliedFilterCount: number): SearchEmptyCause {\n // Loading/nonempty results must not bypass the same count contract used by empty results.\n if ((count !== null && (count < 0 || !Number.isSafeInteger(count))) || !Number.isSafeInteger(appliedFilterCount) || appliedFilterCount < 0) {\n throw new RangeError(\"Search counts must be nonnegative integers\");\n }\n if (count === null || count > 0) return \"none\";\n return appliedFilterCount > 0 ? \"filters\" : \"query\";\n}\n\n/**\n * Index to focus after removing item `removedIndex` from a list that now has `remaining` items:\n * the item that slid into its place, else the new last item, else -1 (move to the fallback target).\n * Removing a focused chip or row would otherwise drop focus to <body>.\n */\nexport function resolveFocusAfterRemoval(removedIndex: number, remaining: number): number {\n if (!Number.isInteger(removedIndex) || removedIndex < 0 || !Number.isInteger(remaining) || remaining < 0) {\n throw new RangeError(\"Removal indexes must be nonnegative integers\");\n }\n return remaining === 0 ? -1 : Math.min(removedIndex, remaining - 1);\n}\n\n/** Recipe for the SearchScreen phase sections; geometry stays on shared spacing tokens. */\nexport const searchScreenRecipe = {\n /** Debounced typing delay; explicit submit remains a separate host action. */\n debounceMs: 300,\n /** Recent searches shown before the user types; reference services show 5–10 and let the rest scroll away. */\n recentVisible: 5,\n /** Suggestions under the \"search for ‘q’\" row. */\n suggestionVisible: 6,\n /** Skeleton rows while the first page of results loads. */\n loadingRows: 4,\n /** Between idle sections (recent, suggested). */\n sectionGap: spacing.xl,\n /** Section title to its list, and results header to applied filters. */\n headerGap: spacing.sm,\n /** Between chips in applied filters and suggested queries. */\n chipGap: spacing.xs,\n} as const;\n\n/** Keep finite negative delays at zero; reject values whose timer behavior varies by host. */\nexport function resolveSearchDebounceMs(value: number = searchScreenRecipe.debounceMs): number {\n if (!Number.isFinite(value)) throw new RangeError(\"Search debounceMs must be finite\");\n return Math.max(0, value);\n}\n\n/** Horizontal intent preserves vertical scrolling and uses one reveal distance across renderers. */\nexport function timestampRevealOffset(dx: number, dy: number): number {\n // A 12px dead zone and 2:1 direction bias avoid turning taps/list scrolling into a time gesture.\n return dx > 12 && dx > Math.abs(dy) * 2 ? Math.min(dx, 88) : 0;\n}\n\n/** Notification previews need an actor/type badge and a separate subject thumbnail.\n * Keep this geometry shared so inboxes do not recreate the same row per product. */\nexport const notificationRowRecipe = {\n gap: 12, contentGap: 4, avatarSize: 44, avatarBadgeSize: 20,\n thumbnailSize: 44, unreadSize: 6, previewLines: 2, paddingBlock: 12, paddingInline: 16,\n} as const;\n\n/** Shared profile identity geometry; product owns the avatar content. */\nexport const profileSummaryRecipe = Object.freeze({ avatarSize: 72 });\n\n/** Launcher artwork stays above its caption; product overlays may extend beyond the icon frame. */\nexport const iconTileRecipe = Object.freeze({ iconSize: 64, labelMaxWidth: 72, multilineLabelMaxWidth: 84, multilineLabelMinHeight: 44, ghostOpacity: 0.55, gap: 6, iconRadius: \"22%\" });\n"]}
|
|
1
|
+
{"version":3,"file":"screen-patterns.js","sourceRoot":"","sources":["../src/screen-patterns.ts"],"names":[],"mappings":"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","sourcesContent":["import { glyph, layout, radius, spacing } from \"./foundations.js\";\nimport { avatarRecipe } from \"./component-recipes.js\";\nimport type { MenuItemDescriptor } from \"./behaviors.js\";\n\n/** Initial load replaces the body; refresh/save errors belong beside retained content. */\nexport type ScreenContentState =\n | Readonly<{ kind: \"ready\" }>\n | Readonly<{ kind: \"loading\" | \"empty\" | \"error\" | \"restricted\"; title: string; description?: string }>;\n\nexport function resolveScreenContentState(state: ScreenContentState = { kind: \"ready\" }) {\n if (![\"ready\", \"loading\", \"empty\", \"error\", \"restricted\"].includes(state.kind)) {\n throw new TypeError(\"Unknown screen content state\");\n }\n if (state.kind !== \"ready\" && !state.title.trim()) {\n throw new TypeError(\"Screen state requires a localized title\");\n }\n return {\n kind: state.kind,\n replacesContent: state.kind !== \"ready\",\n busy: state.kind === \"loading\",\n announcement: state.kind === \"error\" ? \"assertive\" : \"polite\",\n } as const;\n}\n\n/**\n * Native header band heights. Titled centered headers match the iOS navigation bar (44 control + 4 + 4);\n * icon-only centered headers are compact (2026-10-14 야잘알 tab spacing, 2026-10-17 \"상단 여백 줄여\").\n * Body top padding shrinks only under a compact header without a notice.\n */\nexport const screenHeaderRecipe = {\n minHeight: 52,\n paddingVertical: spacing.xxs,\n compactMinHeight: 48,\n compactPaddingVertical: 2,\n compactBodyTop: spacing.xxs,\n /**\n * Heading levels for the route title, shared by Web and Native (2026-10-17 comparison: Native drew the\n * title as regular-weight Text — 20 start / 18 centered — while Web used bold Heading levels).\n */\n titleLevel: \"level3\",\n centeredTitleLevel: \"level5\",\n} as const;\n\n/**\n * Leaving a screen (back, close, \"설정 나가기\") is an icon-only button fixed at the header's leading edge\n * (2026-10-17 user rule: exits had drifted into body text buttons with mixed glyphs). The label is read\n * by assistive tech only. `back` mirrors in RTL; `close` is for modal-style routes.\n */\nexport type ScreenExitKind = \"back\" | \"close\";\nexport const screenExitRecipe = {\n /** Chevron arm length and stroke; close cross arm length. Drawn, not font glyphs, so every platform matches. */\n chevronSize: 10,\n closeSize: 14,\n stroke: 2,\n} as const;\nexport function validateScreenExit(exit: Readonly<{ kind: string; label: string }>, hasLeading: boolean) {\n if (exit.kind !== \"back\" && exit.kind !== \"close\") throw new TypeError(\"Screen exit kind must be back or close\");\n if (!exit.label.trim()) throw new TypeError(\"Screen exit needs a localized accessible label\");\n if (hasLeading) throw new TypeError(\"Screen exit owns the leading slot; do not also pass leading\");\n}\n\n/**\n * Who owns the screen gutters. `default`: the shared shell pads header, notice, body and footer. `none`: the host\n * route already insets everything (≈45 product call sites rely on this meaning, so it cannot change).\n * `body-edge`: header, notice and footer keep the shell padding; only the body's inline padding is 0 so full-width\n * list rows (ConversationRow, ListRow-based items) supply their own inset — review S5#9 measured DM avatars ~32pt\n * from the edge because body padding and row padding stacked (2026-10-17 user decision).\n */\nexport type ScreenContentInset = \"default\" | \"none\" | \"body-edge\";\nexport const screenContentInsets = [\"default\", \"none\", \"body-edge\"] as const satisfies readonly ScreenContentInset[];\n\n/**\n * 화면 진입 시 첫 입력 포커스(2026-10-18 사용자 요청: \"input이 있는 화면에 진입하면 포커스되도록, 웹앱 둘 다\").\n * 앱마다 autoFocus를 따로 붙이던 일을 화면 골격이 맡는다. 입력 칸은 가장 가까운 화면·시트 범위에 자신을 등록하고,\n * 범위가 진입이 끝난 뒤(Native: 전환·애니메이션 interaction 뒤, Web: mount 직후) 아래 규칙으로 한 번 고른다.\n *\n * - `first-input`: `initialFocusTarget`을 준 칸이 있으면 그 칸, 없으면 등록 순서상 첫 칸. 입력이 화면의 주 행동인 구성\n * (검색, 작성·편집)의 기본값이다.\n * - `single-input`: 등록된 텍스트 입력이 정확히 하나일 때만 그 칸. 시트·대화상자의 기본값이다 — 칸이 여럿이면 어느\n * 것이 주인지 알 수 없어 기존 포커스 규칙(첫 포커스 가능 요소·덜 파괴적인 행동)을 그대로 둔다.\n * - `none`: 고르지 않는다. 일반 화면과, 입력이 읽기의 보조인 대화·댓글 화면의 기본값이다 — 키보드가 올라오면 읽던\n * 기록을 가린다. 같은 prop으로 켤 수 있다.\n *\n * 비활성·읽기 전용 칸은 고르지 않고 `initialFocusTarget={false}` 칸은 제외한다. 화면 범위는 mount당 한 번만 포커스한다:\n * 스택에서 돌아온 화면(이미 mount된 화면)을 다시 포커스하면 키보드가 돌아온 맥락을 가리고, HJM은 내비게이션 포커스\n * 신호를 알지 못한다. 시트·대화상자는 열릴 때마다 다시 고른다. 모션 감소는 애니메이션에만 적용하고 포커스는 그대로 한다.\n */\nexport type InitialFocusMode = \"first-input\" | \"single-input\" | \"none\";\nexport type ScreenInitialFocus = \"first-input\" | \"none\";\nexport type InitialFocusCandidate = Readonly<{\n /** Registration order inside the scope (tree order). */\n order: number;\n /** `initialFocusTarget` on the field: true prefers it, false excludes it, undefined keeps it eligible. */\n preference: boolean | undefined;\n /** False for disabled or read-only fields at resolve time. */\n focusable: boolean;\n}>;\n\n/** Defaults per composition; renderers read these instead of repeating literals. */\nexport const initialFocusDefaults = {\n screen: \"none\",\n search: \"first-input\",\n editor: \"first-input\",\n chat: \"none\",\n commentThread: \"none\",\n overlay: \"single-input\",\n // Auth screens lead with provider buttons; a signup nickname step opts in with `initialFocus=\"first-input\"`.\n auth: \"none\",\n} as const satisfies Record<string, InitialFocusMode>;\n\nexport function resolveInitialFocusTarget<T extends InitialFocusCandidate>(candidates: readonly T[], mode: InitialFocusMode): T | null {\n if (mode === \"none\") return null;\n const ordered = [...candidates].sort((a, b) => a.order - b.order);\n if (mode === \"single-input\") {\n const only = ordered.length === 1 ? ordered[0]! : null;\n return only && only.focusable && only.preference !== false ? only : null;\n }\n const eligible = ordered.filter(candidate => candidate.focusable && candidate.preference !== false);\n return eligible.find(candidate => candidate.preference === true) ?? eligible[0] ?? null;\n}\n\n/**\n * 진입 포커스 창(2026-10-18 1.28.1 앱 채택 점검). mount 시점 한 번만 고르면 세 경우가 앱 우회로 남았다: 진입 때 열린\n * 모달 아래 칸(번뚝 첫 가입 약관), 진입 중 비동기로 나타나는 칸(번뚝 계정 삭제 확인), 사용자 행동으로 나중에 나타나는 칸\n * (utilverse 검색 열기, 번뚝 아이디어 시트·spint 작성 단계). 그래서 범위는 아래 상태를 가진다.\n *\n * - `entering`: 진입 중(Native 전환·시트 등장 interaction 전). 칸 등록만 받는다.\n * - `open`: 진입이 끝났지만 아직 포커스하지 못했다. 칸이 새로 등록되거나 위 오버레이가 닫히면 다시 고른다. 모달 아래에서\n * 진입한 화면은 모달이 닫힐 때 사용자가 그 화면을 아직 만지지 않았으면 그때 포커스한다.\n * - `settled`: 포커스했거나, 사용자가 범위를 직접 조작(터치·포인터·키·휠)했거나, 이미 다른 텍스트 칸에 초점이 있다.\n * 이후에는 `initialFocusTarget`을 준 칸이 새로 나타날 때만 그 칸을 포커스한다 — 검색 열기·단계 이동처럼 사용자\n * 행동으로 드러난 주 입력이다. 이 규칙은 `initialFocus` 모드와 무관하다(`none` 화면의 검색 칸도 드러날 때 포커스).\n *\n * 위에 다른 오버레이가 열려 있는 동안(`blocked`)은 고르지 않고, 그 동안의 조작은 아래 범위의 조작으로 세지 않는다\n * (약관 동의 탭이 화면의 진입 포커스를 끝내면 안 된다). 텍스트 칸에 이미 초점이 있으면 빼앗지 않는다.\n */\nexport type EntryFocusPhase = \"inactive\" | \"entering\" | \"open\" | \"settled\";\nexport type EntryFocusEvent<T extends InitialFocusCandidate> =\n /** The scope mounted (screen) or opened (overlay). */\n | Readonly<{ kind: \"activate\" }>\n /** The overlay closed or the scope unmounted. */\n | Readonly<{ kind: \"deactivate\" }>\n /** The enter transition finished. */\n | Readonly<{ kind: \"enter\" }>\n /** A field mounted into the scope (first registration of that field instance). */\n | Readonly<{ kind: \"register\"; field: T }>\n /** An overlay above the scope closed. */\n | Readonly<{ kind: \"unblock\" }>\n /** User touch, pointer, key or wheel input reached the scope. */\n | Readonly<{ kind: \"interact\" }>;\nexport type EntryFocusFacts<T extends InitialFocusCandidate> = Readonly<{\n mode: InitialFocusMode;\n /** Every field registered in the scope now, including a newly registered one. */\n candidates: readonly T[];\n /** Another overlay is open above this scope. */\n blocked: boolean;\n /** A text field already has focus (the user's or the app's). */\n textEntryFocused: boolean;\n}>;\nexport type EntryFocusResolution<T> = Readonly<{ phase: EntryFocusPhase; target: T | null }>;\n\nexport function resolveEntryFocus<T extends InitialFocusCandidate>(phase: EntryFocusPhase, event: EntryFocusEvent<T>, facts: EntryFocusFacts<T>): EntryFocusResolution<T> {\n const stay = { phase, target: null };\n if (event.kind === \"deactivate\") return { phase: \"inactive\", target: null };\n if (event.kind === \"activate\") return { phase: \"entering\", target: null };\n if (phase === \"inactive\") return stay;\n if (event.kind === \"interact\") return facts.blocked || phase === \"settled\" ? stay : { phase: \"settled\", target: null };\n const attempt = (): EntryFocusResolution<T> => {\n if (facts.blocked) return { phase: \"open\", target: null };\n if (facts.textEntryFocused) return { phase: \"settled\", target: null };\n const target = resolveInitialFocusTarget(facts.candidates, facts.mode);\n return target ? { phase: \"settled\", target } : { phase: \"open\", target: null };\n };\n if (event.kind === \"enter\") return phase !== \"entering\" ? stay : facts.mode === \"none\" ? { phase: \"settled\", target: null } : attempt();\n if (phase === \"entering\") return stay;\n if (phase === \"open\") return attempt();\n if (event.kind !== \"register\") return stay;\n const { field } = event;\n return field.preference === true && field.focusable && !facts.blocked && !facts.textEntryFocused ? { phase, target: field } : stay;\n}\n\n// Reuse reading-width and spacing tokens; do not derive geometry from a product's device or artwork.\nexport const screenPatternRecipe = {\n maxWidth: layout.readingMaxWidth,\n padding: spacing.md,\n sectionGap: spacing.xl,\n itemGap: spacing.sm,\n stateGap: spacing.md,\n // Compact screens must keep back/title/save on one row; scale this floor for large text instead of reserving a desktop-width title.\n headerMinWidth: layout.readingMaxWidth / 6,\n // Reserve the opposite edge for authorship and cap the composer so history remains visible.\n messageMaxWidth: \"84%\",\n // Social thumbnails stay compact; selection order and removal replace a second toolbar.\n attachmentSize: 80,\n attachmentRemoveSize: 24,\n reactionHoldMs: 450,\n reactionMoveTolerance: 10,\n reactionMenuWidth: 320,\n replySwipeDistance: 60,\n composerMinLines: 1,\n composerMaxLines: 5,\n} as const;\n\n/** Controlled composer: HJM never clears drafts or interprets a fulfilled callback as server delivery. */\nexport type MessageComposerDescriptor = Readonly<{\n value: string;\n label: string;\n sendLabel: string;\n /** Short visual copy may differ from the complete accessible input name. */\n placeholder?: string;\n description?: string;\n error?: string;\n invalid?: boolean;\n /** Newline remains the compatible default; desktop chat may explicitly opt into send. */\n submitMode?: \"newline\" | \"send\";\n disabled?: boolean;\n pending?: boolean;\n attachmentCount?: number;\n}>;\n/** Safari may report the final IME Enter as keyCode 229 after isComposing becomes false. */\nexport function shouldSubmitMessageKey(event: Readonly<{ key: string; shiftKey?: boolean; isComposing?: boolean; keyCode?: number }>, mode: \"newline\" | \"send\" = \"newline\"): boolean {\n return mode === \"send\" && event.key === \"Enter\" && !event.shiftKey && !event.isComposing && event.keyCode !== 229;\n}\nexport function canSubmitMessage({ value, disabled = false, pending = false, attachmentCount = 0 }: MessageComposerDescriptor): boolean {\n if (!Number.isSafeInteger(attachmentCount) || attachmentCount < 0) throw new RangeError(\"Attachment count must be a nonnegative integer\");\n return !disabled && !pending && (value.trim().length > 0 || attachmentCount > 0);\n}\n\n/**\n * Shared timeline geometry. 2026-10-16 user decision: the common chat standard follows the measured\n * KakaoTalk iOS chat room (@3x capture: bubble ~35pt tall, radius ~14, run gap ~6, group gap ~12,\n * avatar ~34, avatar gap 8). Brand colors and artwork are not copied; surfaces stay semantic tokens.\n */\nexport const chatMessageRecipe = {\n // Must be a size the Avatar renders on both platforms: 36 was no Web Avatar step (32/40/48/64), so Web drew a 32\n // avatar in a 36 slot while Native drew 36 (2026-10-17 measured audit). `small` is the step nearest the ~34 reference.\n avatarSize: avatarRecipe.sizes.small,\n avatarGap: spacing.xs,\n authorGap: spacing.xxs,\n metaGap: spacing.xxs,\n bubbleRadius: 14,\n bubblePaddingInline: 10,\n bubblePaddingBlock: 6,\n // Bubbles of one run read as a stack; a new author or minute starts a visibly separate group.\n runGap: 6,\n groupGap: spacing.sm,\n // Flat-topped tip continuing the bubble's top edge; the tipped corner tightens to meet it.\n tailWidth: 7,\n tailHeight: 10,\n tailCornerRadius: 4,\n jumpToLatestGap: spacing.xs,\n // Timeline side gutter (measured 10pt); header and composer keep the screen padding.\n timelineInset: 10,\n // Photos render without the bubble surface (measured reference: ~210pt wide, bubble radius).\n mediaWidth: 210,\n mediaGap: 2,\n} as const;\n\n/** Column count for a photo set: pairs read as 2-up, other counts as 3-up; one photo spans the width. */\nexport function resolveChatMediaColumns(count: number): 1 | 2 | 3 {\n if (!Number.isSafeInteger(count) || count < 1) throw new RangeError(\"Chat media requires at least one item\");\n return count === 1 ? 1 : count === 2 || count === 4 ? 2 : 3;\n}\n\n/**\n * Long-press menu geometry measured from the Instagram iOS DM hold menu (2026-10-16 @3x capture):\n * full-width reaction strip ~60pt with ~30pt emoji, the pressed bubble itself as preview, and a ~200pt\n * action card aligned to the bubble's side with ~56pt rows. 12pt between the three blocks.\n */\n/** Emoji row above a comment composer (Instagram comment sheet, 2026-10-16): evenly spread 44pt targets. */\nexport const composerQuickInsertRecipe = { itemSize: 44, emojiSize: 26, gap: spacing.xs } as const;\n\nexport const holdMenuRecipe = {\n inset: 10,\n gap: spacing.sm,\n stripHeight: 60,\n stripItemSize: 48,\n emojiSize: 28,\n actionWidth: 200,\n actionRowHeight: 56,\n actionRadius: 18,\n iconSize: 24,\n} as const;\n\n/** Position inside a run of consecutive messages from one author within one displayed minute. */\nexport type ChatMessageGroupPosition = \"single\" | \"first\" | \"middle\" | \"last\";\n\n/**\n * Runs break when the author or the displayed timestamp changes, so each minute shows its time once\n * and a new minute re-introduces the author (KakaoTalk behavior). Products pass the same localized\n * timestamp string they render; HJM never parses dates.\n */\nexport function resolveChatMessageGroups(items: readonly Readonly<{ id: string; authorId: string; timestamp: string }>[]): ReadonlyMap<string, ChatMessageGroupPosition> {\n const positions = new Map<string, ChatMessageGroupPosition>();\n items.forEach((item, index) => {\n if (!item.id.trim() || positions.has(item.id)) throw new TypeError(\"Chat messages require unique, nonempty ids\");\n const same = (other: (typeof items)[number] | undefined) => !!other && other.authorId === item.authorId && other.timestamp === item.timestamp;\n const before = same(items[index - 1]), after = same(items[index + 1]);\n positions.set(item.id, before ? (after ? \"middle\" : \"last\") : after ? \"first\" : \"single\");\n });\n return positions;\n}\n\n/** What one bubble shows for its run position; both renderers read this instead of re-deriving rules. */\nexport function resolveChatMessageGroupDisplay(position: ChatMessageGroupPosition = \"single\") {\n if (![\"single\", \"first\", \"middle\", \"last\"].includes(position)) throw new TypeError(\"Unknown chat message group position\");\n const starts = position === \"single\" || position === \"first\";\n const ends = position === \"single\" || position === \"last\";\n return { showAuthor: starts, showAvatar: starts, showTail: starts, showTimestamp: ends, spacingBefore: starts ? chatMessageRecipe.groupGap : chatMessageRecipe.runGap } as const;\n}\n\n/** Bubble alignment expresses authorship, not delivery; delivery text always comes from the product receipt. */\nexport type ChatMessageDescriptor = Readonly<{\n direction: \"incoming\" | \"outgoing\";\n author: string;\n timestamp: string;\n deliveryLabel?: string;\n /** Inward drag reveals time (incoming right, outgoing left) while delivery state remains visible; default shows time beside the last bubble of a run. */\n timestampPresentation?: \"always\" | \"swipe\";\n /** Authorship tip on the run's first bubble. Default on since the 2026-10-16 timeline standard. */\n bubbleTail?: boolean;\n /** From resolveChatMessageGroups; omitted means a standalone message. */\n groupPosition?: ChatMessageGroupPosition;\n}>;\n\n/** A denied permission goes to settings; rendering never requests OS access automatically. */\nexport type PermissionScreenStatus = \"prompt\" | \"denied\" | \"granted\" | \"unavailable\";\nexport function resolvePermissionAction(status:PermissionScreenStatus) {\n switch(status){case \"prompt\":return \"request\";case \"denied\":return \"settings\";case \"granted\":return \"continue\";case \"unavailable\":return null;default:throw new TypeError(\"Unknown permission state\");}\n}\nexport function resolveOnboardingStep(total:number,index:number){\n if(!Number.isInteger(total)||total<1||!Number.isInteger(index)||index<0||index>=total)throw new RangeError(\"Onboarding requires a valid step index\");\n return {first:index===0,last:index===total-1};\n}\n\n/**\n * Shared comment-row geometry. 2026-10-16 user decision: comments follow the measured Instagram iOS\n * comment sheet (@3x capture: avatar 32 / reply 24, avatar gap 8, like count under the heart,\n * \"Reply\" as quiet text below the body, replies indented to the text column). Artwork is not copied.\n */\nexport const commentThreadRecipe = {\n avatarSize: 32,\n replyAvatarSize: 24,\n avatarGap: spacing.xs,\n lineGap: 2,\n rowGap: spacing.sm,\n // Replies align with the parent's text column instead of an arbitrary section inset.\n replyIndent: 32 + spacing.xs,\n // The heart keeps the 44pt touch target even though the measured reference draws a smaller glyph.\n likeColumnWidth: 44,\n // Optional photo/sticker under the body; the measured reference keeps it thumbnail-sized.\n mediaMaxWidth: 160,\n mediaRadius: radius.md,\n // The trailing vertical-dots menu glyph; the button keeps the shared 44pt IconButton target.\n menuGlyphSize: glyph.sm,\n /**\n * Trailing actions (like, product actions, more) centre their 44 targets on the identity's first line instead of\n * top-aligning the target box (2026-10-17 measured audit: avatar 168 / author line 162 / glyphs 174). The cluster\n * shifts by (first-line height − visible target) / 2 — negative while the line is shorter than the target — and the\n * last control takes IconButton `edge=\"end\"` so its glyph slot ends on the row inset like the avatar starts on it.\n * The first line is the author caption, or the body line when the author runs inline with `bodyText`.\n */\n actionAnchor: { authorTextVariant: \"caption\", inlineTextVariant: \"body\" },\n} as const;\n\n/**\n * Items of the HJM-owned per-comment \"more\" menu (2026-10-17: message/comment structure belongs to HJM, review S4#7).\n * Same vocabulary as Menu/ContextMenu; the product supplies only ids, localized labels, tone and availability.\n */\nexport type CommentMenuItemDescriptor<Key extends string = string> = Pick<MenuItemDescriptor<Key>, \"id\" | \"label\" | \"disabled\" | \"tone\">;\n/** Danger actions (delete, block) always sit last so a destructive row is never the first target; order is otherwise kept. */\nexport function resolveCommentMenuItems<Key extends string>(items: readonly CommentMenuItemDescriptor<Key>[]): readonly CommentMenuItemDescriptor<Key>[] {\n const ids = new Set<string>();\n for (const item of items) {\n if (!item.id.trim() || ids.has(item.id) || !item.label.trim()) throw new TypeError(\"Comment menu items require unique ids and localized labels\");\n ids.add(item.id);\n }\n return [...items.filter(item => item.tone !== \"danger\"), ...items.filter(item => item.tone === \"danger\")];\n}\n\n/** Replies are one level deep; reject orphaned/duplicate records instead of silently losing them. */\nexport function validateCommentThread(items:readonly {id:string;parentId:string|null}[]){\n const roots=new Set(items.filter(item=>item.parentId===null).map(item=>item.id));const ids=new Set<string>();\n for(const item of items){if(!item.id.trim()||ids.has(item.id))throw new TypeError(\"Comment ids must be unique and nonempty\");ids.add(item.id);if(item.parentId!==null&&(!roots.has(item.parentId)||item.parentId===item.id))throw new TypeError(\"Replies require an existing root comment\");}\n}\n\n/** Source bytes, permission requests, ordering and upload limits remain product-owned. */\nexport type MessageAttachmentDescriptor = Readonly<{ id: string; removeLabel: string; /** Local preparation can lock removal without locking text entry. */ disabled?: boolean }>;\nexport function validateMessageAttachments(attachments: readonly MessageAttachmentDescriptor[]): void {\n const ids = new Set<string>();\n for (const item of attachments) {\n if (!item.id.trim() || ids.has(item.id) || !item.removeLabel.trim()) throw new TypeError(\"Attachments require unique ids and localized removal labels\");\n ids.add(item.id);\n }\n}\n\n/** Require horizontal intent so a timeline scroll cannot accidentally start a reply. */\nexport function isReplySwipe(dx: number, dy: number): boolean {\n return Math.abs(dx) >= screenPatternRecipe.replySwipeDistance && Math.abs(dx) > Math.abs(dy) * 2;\n}\n\n/** The UI never infers permission or camera availability; product adapters own both. */\nexport type PhotoSource = \"library\" | \"camera\";\nexport type PhotoSourceLabels = Readonly<{ title:string; library:string; camera:string; cancel:string }>;\n\nexport type SavedItem = Readonly<{ id: string; title: string }>;\nexport type SavedCollection = Readonly<{ id: string; title: string; itemIds: readonly string[] }>;\nexport type SavedItemsLabels = Readonly<{ allItems: string; privateNotice: string; back: string; empty: string; createCollection: string }>;\n\n/** Unsave removes an item from every collection view without rewriting product-owned membership. */\nexport function resolveSavedItems<T extends SavedItem>(items:readonly T[],collections:readonly SavedCollection[],collectionId:string|null|undefined,selectedItemId:string|null|undefined){\n const ids=new Set<string>(),groups=new Set<string>();\n for(const item of items){if(!item.id.trim()||ids.has(item.id)||!item.title.trim())throw new TypeError(\"Saved items require unique ids and nonempty titles\");ids.add(item.id);}\n for(const group of collections){if(!group.id.trim()||groups.has(group.id)||!group.title.trim())throw new TypeError(\"Saved collections require unique ids and nonempty titles\");groups.add(group.id);}\n const collection=collections.find(item=>item.id===collectionId);\n // A deleted collection returns to the overview instead of showing a mislabeled all-posts view.\n const home=collectionId===undefined||(collectionId!==null&&!collection);\n const visible=home||collectionId===null?items:items.filter(item=>collection?.itemIds.includes(item.id));\n return {home,collection,visible,selected:home?undefined:visible.find(item=>item.id===selectedItemId)};\n}\n\n/**\n * SearchScreen phases (2026-10-06 search redesign, docs/screen-patterns.md#searchscreen-두-단계-검색).\n * Without a committed query (one-step search, the pre-1.13 behavior) any nonblank query is already\n * `results`. With one, typing a different query is `typing`: suggestions replace the results until the\n * user commits (Enter, a suggestion, a recent or suggested query). Comparing trimmed values keeps a\n * trailing space from flipping committed results back into suggestions.\n */\nexport type SearchScreenPhase = \"idle\" | \"typing\" | \"results\";\nexport function resolveSearchScreenPhase(query: string, committedQuery?: string): SearchScreenPhase {\n const typed = query.trim();\n if (!typed) return \"idle\";\n if (committedQuery === undefined) return \"results\";\n return typed === committedQuery.trim() ? \"results\" : \"typing\";\n}\n\n/**\n * The value a commit records, or `null` when there is nothing to commit. Blank commits are dropped\n * so a stray Enter never writes an empty recent search or fetches \"everything\".\n */\nexport function resolveSearchCommit(value: string): string | null {\n const next = value.trim();\n return next ? next : null;\n}\n\n/**\n * Why a committed search shows nothing. `filters` keeps the filter rail and offers \"clear all\";\n * `query` hides the rail (no filter can fix it) and offers suggested queries instead. Reference\n * services hide the rail on every zero result, which removes the only way to undo a filter.\n * `null` count means the result is still loading, so no cause is reported yet.\n */\nexport type SearchEmptyCause = \"none\" | \"filters\" | \"query\";\nexport function resolveSearchEmptyCause(count: number | null, appliedFilterCount: number): SearchEmptyCause {\n // Loading/nonempty results must not bypass the same count contract used by empty results.\n if ((count !== null && (count < 0 || !Number.isSafeInteger(count))) || !Number.isSafeInteger(appliedFilterCount) || appliedFilterCount < 0) {\n throw new RangeError(\"Search counts must be nonnegative integers\");\n }\n if (count === null || count > 0) return \"none\";\n return appliedFilterCount > 0 ? \"filters\" : \"query\";\n}\n\n/**\n * Index to focus after removing item `removedIndex` from a list that now has `remaining` items:\n * the item that slid into its place, else the new last item, else -1 (move to the fallback target).\n * Removing a focused chip or row would otherwise drop focus to <body>.\n */\nexport function resolveFocusAfterRemoval(removedIndex: number, remaining: number): number {\n if (!Number.isInteger(removedIndex) || removedIndex < 0 || !Number.isInteger(remaining) || remaining < 0) {\n throw new RangeError(\"Removal indexes must be nonnegative integers\");\n }\n return remaining === 0 ? -1 : Math.min(removedIndex, remaining - 1);\n}\n\n/** Recipe for the SearchScreen phase sections; geometry stays on shared spacing tokens. */\nexport const searchScreenRecipe = {\n /** Debounced typing delay; explicit submit remains a separate host action. */\n debounceMs: 300,\n /** Recent searches shown before the user types; reference services show 5–10 and let the rest scroll away. */\n recentVisible: 5,\n /** Suggestions under the \"search for ‘q’\" row. */\n suggestionVisible: 6,\n /** Skeleton rows while the first page of results loads. */\n loadingRows: 4,\n /** Between idle sections (recent, suggested). */\n sectionGap: spacing.xl,\n /** Section title to its list, and results header to applied filters. */\n headerGap: spacing.sm,\n /** Between chips in applied filters and suggested queries. */\n chipGap: spacing.xs,\n} as const;\n\n/** Keep finite negative delays at zero; reject values whose timer behavior varies by host. */\nexport function resolveSearchDebounceMs(value: number = searchScreenRecipe.debounceMs): number {\n if (!Number.isFinite(value)) throw new RangeError(\"Search debounceMs must be finite\");\n return Math.max(0, value);\n}\n\n/** Horizontal intent preserves vertical scrolling and uses one reveal distance across renderers. */\nexport function timestampRevealOffset(dx: number, dy: number): number {\n // A 12px dead zone and 2:1 direction bias avoid turning taps/list scrolling into a time gesture.\n return dx > 12 && dx > Math.abs(dy) * 2 ? Math.min(dx, 88) : 0;\n}\n\n/** Notification previews need an actor/type badge and a separate subject thumbnail.\n * Keep this geometry shared so inboxes do not recreate the same row per product. */\nexport const notificationRowRecipe = {\n gap: 12, contentGap: 4, avatarSize: 44, avatarBadgeSize: 20,\n thumbnailSize: 44, unreadSize: 6, previewLines: 2, paddingBlock: 12, paddingInline: 16,\n} as const;\n\n/** Shared profile identity geometry; product owns the avatar content. */\nexport const profileSummaryRecipe = Object.freeze({ avatarSize: 72 });\n\n/** Launcher artwork stays above its caption; product overlays may extend beyond the icon frame. */\nexport const iconTileRecipe = Object.freeze({ iconSize: 64, labelMaxWidth: 72, multilineLabelMaxWidth: 84, multilineLabelMinHeight: 44, ghostOpacity: 0.55, gap: 6, iconRadius: \"22%\" });\n"]}
|
package/dist/showcase.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"showcase.d.ts","sourceRoot":"","sources":["../src/showcase.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"showcase.d.ts","sourceRoot":"","sources":["../src/showcase.ts"],"names":[],"mappings":"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"}
|
package/dist/showcase.js
CHANGED
|
@@ -150,6 +150,10 @@ const textlessComponentNames = new Set([
|
|
|
150
150
|
// These own form/range behavior but no long-form text slot; their child fields
|
|
151
151
|
// and calendar cells own their copy, so duplicating that proof here misattributes it.
|
|
152
152
|
"Form", "DateRangePicker",
|
|
153
|
+
// 2026-10-18: Chart's category/series labels are short identifiers and its text alternative is a hidden
|
|
154
|
+
// description for assistive technology; ImageChoiceGroup tiles carry accessible names, not visible copy.
|
|
155
|
+
// Neither has a long-form text slot, so the long-copy proof would measure a product caption, not the component.
|
|
156
|
+
"Chart", "ImageChoiceGroup",
|
|
153
157
|
]);
|
|
154
158
|
// These behaviors expose no interaction on either rendered surface.
|
|
155
159
|
const semanticOnlyBehaviors = new Set([
|
|
@@ -177,6 +181,9 @@ const nativeActionBehaviors = new Set([
|
|
|
177
181
|
"toggleGroup", "transferList", "uploadItem",
|
|
178
182
|
// 2026-10-14: Native DataTable sort/row actions and chart adjustable stepping.
|
|
179
183
|
"dataTable", "chart",
|
|
184
|
+
// 2026-10-18: Pagination became shared with a Native beta renderer (1bae9c1a); its page buttons declare the
|
|
185
|
+
// activate action, so the Native surface owns a native-actions requirement like every other action behavior.
|
|
186
|
+
"pagination",
|
|
180
187
|
]);
|
|
181
188
|
function getRendererShowcaseScenarios(entry, surface) {
|
|
182
189
|
const requirements = rendererRequirements.filter((scenario) => scenario !== "long-copy" || !textlessComponentNames.has(entry.name));
|
package/dist/showcase.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"showcase.js","sourceRoot":"","sources":["../src/showcase.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n componentCatalog,\n getComponentSurfaceStatus,\n type ComponentCatalogEntry,\n type ComponentStatus,\n type ComponentSurfaceMaturity,\n type ComponentSurfaceStatus,\n} from \"./catalog.js\";\nimport type { BehaviorName } from \"./behaviors.js\";\nimport type { ResolvedTheme } from \"./colors.js\";\nimport type {\n DesignSystemDirection,\n DesignSystemEnvironmentInput,\n DesignSystemTextScale,\n} from \"./design-system-provider.js\";\n\nexport type ShowcaseTheme = ResolvedTheme;\nexport type ShowcaseDirection = DesignSystemDirection;\n/** Closed fixture subset of the Provider's continuous text-scale signal. */\nexport type ShowcaseTextScale = 1 | 1.5 | 2;\nexport type ShowcaseMotionPreference = \"full\" | \"reduced\";\n\nexport type ShowcaseEnvironment = Readonly<{\n id: \"default\" | \"dark\" | \"large-text\" | \"rtl\" | \"reduced-motion\";\n label: string;\n theme: ShowcaseTheme;\n direction: ShowcaseDirection;\n textScale: ShowcaseTextScale;\n motion: ShowcaseMotionPreference;\n}>;\n\n/**\n * A small, deliberate environment matrix catches the high-risk differences\n * without multiplying every story into an unreadable Cartesian product.\n */\nexport const showcaseEnvironmentMatrix = [\n {\n id: \"default\",\n label: \"밝게 · 왼쪽→오른쪽 · 100%\",\n theme: \"light\",\n direction: \"ltr\",\n textScale: 1,\n motion: \"full\",\n },\n {\n id: \"dark\",\n label: \"어둡게 · 왼쪽→오른쪽 · 100%\",\n theme: \"dark\",\n direction: \"ltr\",\n textScale: 1,\n motion: \"full\",\n },\n {\n id: \"large-text\",\n label: \"밝게 · 왼쪽→오른쪽 · 200%\",\n theme: \"light\",\n direction: \"ltr\",\n textScale: 2,\n motion: \"full\",\n },\n {\n id: \"rtl\",\n label: \"밝게 · 오른쪽→왼쪽 · 100%\",\n theme: \"light\",\n direction: \"rtl\",\n textScale: 1,\n motion: \"full\",\n },\n {\n id: \"reduced-motion\",\n label: \"밝게 · 왼쪽→오른쪽 · 동작 줄이기\",\n theme: \"light\",\n direction: \"ltr\",\n textScale: 1,\n motion: \"reduced\",\n },\n] as const satisfies readonly ShowcaseEnvironment[];\n\n/** Bridges documentation fixtures to the same environment contract products consume. */\nexport function getShowcaseEnvironmentInput(\n environment: ShowcaseEnvironment,\n): DesignSystemEnvironmentInput {\n const textScale: DesignSystemTextScale = environment.textScale;\n return {\n theme: environment.theme,\n direction: environment.direction,\n textScale,\n reducedMotion: environment.motion === \"reduced\",\n };\n}\n\nexport type ShowcaseScenarioId =\n | \"contract\"\n | \"default\"\n | \"dark\"\n | \"long-copy\"\n | \"large-text\"\n | \"rtl\"\n | \"reduced-motion\"\n | \"accessibility\"\n | \"keyboard\"\n | \"native-actions\"\n | \"platform-parity\";\n\nexport type ShowcaseSurface = \"contract\" | \"web\" | \"native\";\n\nexport type ShowcaseScenario = Readonly<{\n id: ShowcaseScenarioId;\n label: string;\n description: string;\n}>;\n\nexport const showcaseScenarios = [\n {\n id: \"contract\",\n label: \"계약\",\n description: \"구조·기본값·지원 축·플랫폼과 성숙도가 보인다.\",\n },\n {\n id: \"default\",\n label: \"기본\",\n description: \"제품 설정을 덮어쓰지 않고 recipe 기본값으로 보통 상태를 그린다.\",\n },\n {\n id: \"dark\",\n label: \"어두운 테마\",\n description: \"어두운 테마에서도 의미 색이 읽힌다.\",\n },\n {\n id: \"long-copy\",\n label: \"긴 문구\",\n description: \"긴 한국어·영어 문구가 잘리거나 의미를 숨기지 않고 줄바꿈된다.\",\n },\n {\n id: \"large-text\",\n label: \"200% 글자\",\n description: \"글자를 200%까지 키워도 필요한 정보가 잘리지 않는다.\",\n },\n {\n id: \"rtl\",\n label: \"오른쪽→왼쪽\",\n description: \"논리적 시작·끝 배치와 방향 아이콘이 올바르게 뒤집힌다.\",\n },\n {\n id: \"reduced-motion\",\n label: \"동작 줄이기\",\n description: \"움직임이 recipe의 동작 줄이기 대체 표현을 따른다.\",\n },\n {\n id: \"accessibility\",\n label: \"접근성\",\n description: \"이름·상태·관계·대비·터치 영역을 확인할 수 있다.\",\n },\n {\n id: \"keyboard\",\n label: \"키보드\",\n description: \"포커스 순서와 문서화한 키보드 동작을 상호작용 테스트로 실행한다.\",\n },\n {\n id: \"native-actions\",\n label: \"앱 동작\",\n description: \"접근성 동작과 그 상태 변화를 Native renderer에서 실행한다.\",\n },\n {\n id: \"platform-parity\",\n label: \"웹·앱 동등성\",\n description: \"각 renderer가 플랫폼 고유 동작을 쓰면서 같은 의도를 유지한다.\",\n },\n] as const satisfies readonly ShowcaseScenario[];\n\nconst plannedRequirements = [\"contract\"] as const satisfies readonly ShowcaseScenarioId[];\nconst rendererRequirements = [\n \"default\",\n \"dark\",\n \"long-copy\",\n \"large-text\",\n \"rtl\",\n \"reduced-motion\",\n \"accessibility\",\n] as const satisfies readonly Exclude<ShowcaseScenarioId, \"contract\">[];\n\nexport type ShowcaseComponentEntry = Readonly<{\n storyId: string;\n component: ComponentCatalogEntry;\n /** Resolved Web/Native renderer maturity, including legacy catalog inputs. */\n surfaceMaturity: ComponentSurfaceMaturity;\n requirements: readonly ShowcaseEvidenceRequirement[];\n requiredScenarios: readonly ShowcaseScenarioId[];\n requiredSurfaces: readonly ShowcaseSurface[];\n}>;\n\nexport type ShowcaseEvidenceRequirement = Readonly<{\n surface: ShowcaseSurface;\n scenarios: readonly ShowcaseScenarioId[];\n}>;\n\nexport type ShowcaseEvidenceEntry = Readonly<{\n storyId: string;\n surface: ShowcaseSurface;\n scenarios: readonly ShowcaseScenarioId[];\n}>;\n\nexport type ShowcaseCoverageEntry = Readonly<{\n storyId: string;\n component: ComponentCatalogEntry;\n missingEvidence: readonly Readonly<{\n surface: ShowcaseSurface;\n scenario: ShowcaseScenarioId;\n }>[];\n missingSurfaces: readonly ShowcaseSurface[];\n missingScenarios: readonly ShowcaseScenarioId[];\n complete: boolean;\n}>;\n\nexport function getShowcaseStoryId(entry: ComponentCatalogEntry): string {\n const slug = entry.name\n .replace(/([a-z0-9])([A-Z])/g, \"$1-$2\")\n .replace(/[^a-zA-Z0-9]+/g, \"-\")\n .replace(/^-|-$/g, \"\")\n .toLowerCase();\n return `${entry.category}/${slug}`;\n}\n\nexport function getRequiredShowcaseScenarios(\n entry: ComponentCatalogEntry,\n): readonly ShowcaseScenarioId[] {\n const activeSurfaces = ([\"web\", \"native\"] as const).filter((surface) =>\n isRendererMaturity(getComponentSurfaceStatus(entry, surface)),\n );\n if (activeSurfaces.length === 0) return plannedRequirements;\n\n const rendererScenarios = [...new Set(activeSurfaces.flatMap((surface) =>\n getRendererShowcaseScenarios(entry, surface),\n ))];\n return [\n \"contract\",\n ...rendererScenarios,\n ];\n}\n\nfunction isRendererMaturity(\n status: ComponentSurfaceStatus,\n): status is Extract<ComponentStatus, \"stable\" | \"beta\"> {\n return status === \"stable\" || status === \"beta\";\n}\n\n// These outputs expose no consumer-authored visible prose; default and accessibility proofs remain required.\nconst textlessComponentNames: ReadonlySet<string> = new Set([\n \"Icon\", \"IconButton\", \"Skeleton\", \"Spinner\", \"ThinkingOrb\", \"Divider\",\n \"Avatar\", \"Asset\", \"CounterBadge\", \"Image\", \"VisuallyHidden\", \"Pagination\",\n // These own form/range behavior but no long-form text slot; their child fields\n // and calendar cells own their copy, so duplicating that proof here misattributes it.\n \"Form\", \"DateRangePicker\",\n]);\n\n// These behaviors expose no interaction on either rendered surface.\nconst semanticOnlyBehaviors: ReadonlySet<NonNullable<ComponentCatalogEntry[\"behavior\"]>> = new Set([\n \"top\", \"authScreen\", \"heading\", \"bottomInfo\", \"nativePlatform\", \"textFormat\", \"asset\",\n]);\n\n// Keep surface capability lookup local: importing behaviorRegistry here would pull every\n// behavior contract into the lightweight showcase/evidence entry points. The alternative was\n// importing that registry; showcase.test.ts cross-checks these names against it to prevent drift.\nconst webKeyboardBehaviors: ReadonlySet<BehaviorName> = new Set([\n \"agreement\", \"alertDialog\", \"anchor\", \"authProviderButton\", \"bottomNavigation\", \"breadcrumb\",\n \"calendar\", \"carousel\", \"chart\", \"checkbox\", \"checkboxGroup\", \"chip\", \"collapsible\", \"combobox\",\n \"commandPalette\", \"contextMenu\", \"dataTable\", \"datePicker\", \"dateRange\", \"dialog\",\n \"disclosureGroup\", \"field\", \"filePicker\", \"floatingActionButton\", \"form\", \"layout\", \"link\",\n \"loadMore\", \"menu\", \"menubar\", \"numberField\", \"otpField\", \"pagination\", \"passwordField\",\n \"popover\", \"radioGroup\", \"searchField\", \"segmentedControl\", \"select\", \"sheet\", \"sidePanel\",\n \"sidebar\", \"skipNav\", \"slider\", \"splitter\", \"switch\", \"tabs\", \"tagsInput\", \"toast\",\n \"toggleGroup\", \"tooltip\", \"tour\", \"transferList\", \"tree\", \"uploadItem\",\n]);\nconst nativeActionBehaviors: ReadonlySet<BehaviorName> = new Set([\n \"agreement\", \"alertDialog\", \"authProviderButton\", \"bottomNavigation\", \"calendar\", \"carousel\",\n \"checkbox\", \"checkboxGroup\", \"chip\", \"collapsible\", \"combobox\", \"datePicker\", \"dateRange\",\n \"dialog\", \"disclosureGroup\", \"field\", \"filePicker\", \"floatingActionButton\", \"form\", \"link\",\n \"loadMore\", \"menu\", \"numberField\", \"otpField\", \"passwordField\", \"radioGroup\", \"searchField\",\n \"segmentedControl\", \"select\", \"sheet\", \"slider\", \"switch\", \"tabs\", \"tagsInput\", \"toast\",\n \"toggleGroup\", \"transferList\", \"uploadItem\",\n // 2026-10-14: Native DataTable sort/row actions and chart adjustable stepping.\n \"dataTable\", \"chart\",\n]);\n\nfunction getRendererShowcaseScenarios(\n entry: ComponentCatalogEntry,\n surface?: \"web\" | \"native\",\n): readonly Exclude<ShowcaseScenarioId, \"contract\">[] {\n const requirements: Exclude<ShowcaseScenarioId, \"contract\">[] = rendererRequirements.filter(\n (scenario) => scenario !== \"long-copy\" || !textlessComponentNames.has(entry.name),\n );\n // ColorPicker composes native form controls; its text commit/escape behavior still needs real keyboard proof.\n if (entry.name === \"ColorPicker\" && surface === \"web\") requirements.push(\"keyboard\");\n if (entry.behavior && !semanticOnlyBehaviors.has(entry.behavior)) {\n // Web owns DOM key bindings; Native declares host accessibility actions instead, so Pressable tests must not claim physical keyboard proof.\n if (surface === \"web\" && webKeyboardBehaviors.has(entry.behavior)) requirements.push(\"keyboard\");\n if (surface === \"native\" && nativeActionBehaviors.has(entry.behavior)) requirements.push(\"native-actions\");\n }\n return requirements;\n}\n\nexport function getRequiredShowcaseSurfaces(\n entry: ComponentCatalogEntry,\n): readonly ShowcaseSurface[] {\n return getRequiredShowcaseEvidence(entry).map(({ surface }) => surface);\n}\n\nexport function getRequiredShowcaseEvidence(\n entry: ComponentCatalogEntry,\n): readonly ShowcaseEvidenceRequirement[] {\n const requirements: ShowcaseEvidenceRequirement[] = [\n { surface: \"contract\", scenarios: [\"contract\"] },\n ];\n const activeSurfaces = ([\"web\", \"native\"] as const).filter((surface) =>\n isRendererMaturity(getComponentSurfaceStatus(entry, surface)),\n );\n for (const surface of activeSurfaces) {\n requirements.push({ surface, scenarios: getRendererShowcaseScenarios(entry, surface) });\n }\n return requirements;\n}\n\nexport function createShowcaseManifest(\n entries: readonly ComponentCatalogEntry[] = componentCatalog,\n): readonly ShowcaseComponentEntry[] {\n return entries.map((component) => ({\n storyId: getShowcaseStoryId(component),\n component,\n surfaceMaturity: {\n web: getComponentSurfaceStatus(component, \"web\"),\n native: getComponentSurfaceStatus(component, \"native\"),\n },\n requirements: getRequiredShowcaseEvidence(component),\n requiredScenarios: getRequiredShowcaseScenarios(component),\n requiredSurfaces: getRequiredShowcaseSurfaces(component),\n }));\n}\n\nexport const showcaseManifest = createShowcaseManifest();\n\nexport function createShowcaseCoverage(\n evidence: readonly ShowcaseEvidenceEntry[],\n manifest: readonly ShowcaseComponentEntry[] = showcaseManifest,\n): readonly ShowcaseCoverageEntry[] {\n return manifest.map(({ storyId, component, requirements }) => {\n const componentEvidence = evidence.filter((entry) => entry.storyId === storyId);\n const missingEvidence = requirements.flatMap(({ surface, scenarios }) =>\n scenarios\n .filter(\n (scenario) =>\n !componentEvidence.some(\n (entry) => entry.surface === surface && entry.scenarios.includes(scenario),\n ),\n )\n .map((scenario) => ({ surface, scenario })),\n );\n const missingSurfaces = [...new Set(missingEvidence.map(({ surface }) => surface))];\n const missingScenarios = [...new Set(missingEvidence.map(({ scenario }) => scenario))];\n return {\n storyId,\n component,\n missingEvidence,\n missingSurfaces,\n missingScenarios,\n complete: missingSurfaces.length === 0 && missingScenarios.length === 0,\n };\n });\n}\n\nexport function assertShowcaseCoverage(\n evidence: readonly ShowcaseEvidenceEntry[],\n manifest: readonly ShowcaseComponentEntry[] = showcaseManifest,\n): void {\n const missing = createShowcaseCoverage(evidence, manifest).filter(({ complete }) => !complete);\n if (missing.length === 0) return;\n const details = missing\n .map(({ storyId, missingEvidence }) =>\n `${storyId} (${missingEvidence.map(({ surface, scenario }) => `${surface}/${scenario}`).join(\", \") || \"none\"})`,\n )\n .join(\"\\n\");\n throw new Error(`Showcase evidence is incomplete:\\n${details}`);\n}\n\nexport function summarizeShowcaseMaturity(\n entries: readonly ComponentCatalogEntry[] = componentCatalog,\n): Readonly<Record<ComponentStatus, number>> {\n return entries.reduce<Record<ComponentStatus, number>>(\n (summary, entry) => {\n summary[entry.status] += 1;\n return summary;\n },\n { stable: 0, beta: 0, planned: 0, deprecated: 0 },\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"showcase.js","sourceRoot":"","sources":["../src/showcase.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n componentCatalog,\n getComponentSurfaceStatus,\n type ComponentCatalogEntry,\n type ComponentStatus,\n type ComponentSurfaceMaturity,\n type ComponentSurfaceStatus,\n} from \"./catalog.js\";\nimport type { BehaviorName } from \"./behaviors.js\";\nimport type { ResolvedTheme } from \"./colors.js\";\nimport type {\n DesignSystemDirection,\n DesignSystemEnvironmentInput,\n DesignSystemTextScale,\n} from \"./design-system-provider.js\";\n\nexport type ShowcaseTheme = ResolvedTheme;\nexport type ShowcaseDirection = DesignSystemDirection;\n/** Closed fixture subset of the Provider's continuous text-scale signal. */\nexport type ShowcaseTextScale = 1 | 1.5 | 2;\nexport type ShowcaseMotionPreference = \"full\" | \"reduced\";\n\nexport type ShowcaseEnvironment = Readonly<{\n id: \"default\" | \"dark\" | \"large-text\" | \"rtl\" | \"reduced-motion\";\n label: string;\n theme: ShowcaseTheme;\n direction: ShowcaseDirection;\n textScale: ShowcaseTextScale;\n motion: ShowcaseMotionPreference;\n}>;\n\n/**\n * A small, deliberate environment matrix catches the high-risk differences\n * without multiplying every story into an unreadable Cartesian product.\n */\nexport const showcaseEnvironmentMatrix = [\n {\n id: \"default\",\n label: \"밝게 · 왼쪽→오른쪽 · 100%\",\n theme: \"light\",\n direction: \"ltr\",\n textScale: 1,\n motion: \"full\",\n },\n {\n id: \"dark\",\n label: \"어둡게 · 왼쪽→오른쪽 · 100%\",\n theme: \"dark\",\n direction: \"ltr\",\n textScale: 1,\n motion: \"full\",\n },\n {\n id: \"large-text\",\n label: \"밝게 · 왼쪽→오른쪽 · 200%\",\n theme: \"light\",\n direction: \"ltr\",\n textScale: 2,\n motion: \"full\",\n },\n {\n id: \"rtl\",\n label: \"밝게 · 오른쪽→왼쪽 · 100%\",\n theme: \"light\",\n direction: \"rtl\",\n textScale: 1,\n motion: \"full\",\n },\n {\n id: \"reduced-motion\",\n label: \"밝게 · 왼쪽→오른쪽 · 동작 줄이기\",\n theme: \"light\",\n direction: \"ltr\",\n textScale: 1,\n motion: \"reduced\",\n },\n] as const satisfies readonly ShowcaseEnvironment[];\n\n/** Bridges documentation fixtures to the same environment contract products consume. */\nexport function getShowcaseEnvironmentInput(\n environment: ShowcaseEnvironment,\n): DesignSystemEnvironmentInput {\n const textScale: DesignSystemTextScale = environment.textScale;\n return {\n theme: environment.theme,\n direction: environment.direction,\n textScale,\n reducedMotion: environment.motion === \"reduced\",\n };\n}\n\nexport type ShowcaseScenarioId =\n | \"contract\"\n | \"default\"\n | \"dark\"\n | \"long-copy\"\n | \"large-text\"\n | \"rtl\"\n | \"reduced-motion\"\n | \"accessibility\"\n | \"keyboard\"\n | \"native-actions\"\n | \"platform-parity\";\n\nexport type ShowcaseSurface = \"contract\" | \"web\" | \"native\";\n\nexport type ShowcaseScenario = Readonly<{\n id: ShowcaseScenarioId;\n label: string;\n description: string;\n}>;\n\nexport const showcaseScenarios = [\n {\n id: \"contract\",\n label: \"계약\",\n description: \"구조·기본값·지원 축·플랫폼과 성숙도가 보인다.\",\n },\n {\n id: \"default\",\n label: \"기본\",\n description: \"제품 설정을 덮어쓰지 않고 recipe 기본값으로 보통 상태를 그린다.\",\n },\n {\n id: \"dark\",\n label: \"어두운 테마\",\n description: \"어두운 테마에서도 의미 색이 읽힌다.\",\n },\n {\n id: \"long-copy\",\n label: \"긴 문구\",\n description: \"긴 한국어·영어 문구가 잘리거나 의미를 숨기지 않고 줄바꿈된다.\",\n },\n {\n id: \"large-text\",\n label: \"200% 글자\",\n description: \"글자를 200%까지 키워도 필요한 정보가 잘리지 않는다.\",\n },\n {\n id: \"rtl\",\n label: \"오른쪽→왼쪽\",\n description: \"논리적 시작·끝 배치와 방향 아이콘이 올바르게 뒤집힌다.\",\n },\n {\n id: \"reduced-motion\",\n label: \"동작 줄이기\",\n description: \"움직임이 recipe의 동작 줄이기 대체 표현을 따른다.\",\n },\n {\n id: \"accessibility\",\n label: \"접근성\",\n description: \"이름·상태·관계·대비·터치 영역을 확인할 수 있다.\",\n },\n {\n id: \"keyboard\",\n label: \"키보드\",\n description: \"포커스 순서와 문서화한 키보드 동작을 상호작용 테스트로 실행한다.\",\n },\n {\n id: \"native-actions\",\n label: \"앱 동작\",\n description: \"접근성 동작과 그 상태 변화를 Native renderer에서 실행한다.\",\n },\n {\n id: \"platform-parity\",\n label: \"웹·앱 동등성\",\n description: \"각 renderer가 플랫폼 고유 동작을 쓰면서 같은 의도를 유지한다.\",\n },\n] as const satisfies readonly ShowcaseScenario[];\n\nconst plannedRequirements = [\"contract\"] as const satisfies readonly ShowcaseScenarioId[];\nconst rendererRequirements = [\n \"default\",\n \"dark\",\n \"long-copy\",\n \"large-text\",\n \"rtl\",\n \"reduced-motion\",\n \"accessibility\",\n] as const satisfies readonly Exclude<ShowcaseScenarioId, \"contract\">[];\n\nexport type ShowcaseComponentEntry = Readonly<{\n storyId: string;\n component: ComponentCatalogEntry;\n /** Resolved Web/Native renderer maturity, including legacy catalog inputs. */\n surfaceMaturity: ComponentSurfaceMaturity;\n requirements: readonly ShowcaseEvidenceRequirement[];\n requiredScenarios: readonly ShowcaseScenarioId[];\n requiredSurfaces: readonly ShowcaseSurface[];\n}>;\n\nexport type ShowcaseEvidenceRequirement = Readonly<{\n surface: ShowcaseSurface;\n scenarios: readonly ShowcaseScenarioId[];\n}>;\n\nexport type ShowcaseEvidenceEntry = Readonly<{\n storyId: string;\n surface: ShowcaseSurface;\n scenarios: readonly ShowcaseScenarioId[];\n}>;\n\nexport type ShowcaseCoverageEntry = Readonly<{\n storyId: string;\n component: ComponentCatalogEntry;\n missingEvidence: readonly Readonly<{\n surface: ShowcaseSurface;\n scenario: ShowcaseScenarioId;\n }>[];\n missingSurfaces: readonly ShowcaseSurface[];\n missingScenarios: readonly ShowcaseScenarioId[];\n complete: boolean;\n}>;\n\nexport function getShowcaseStoryId(entry: ComponentCatalogEntry): string {\n const slug = entry.name\n .replace(/([a-z0-9])([A-Z])/g, \"$1-$2\")\n .replace(/[^a-zA-Z0-9]+/g, \"-\")\n .replace(/^-|-$/g, \"\")\n .toLowerCase();\n return `${entry.category}/${slug}`;\n}\n\nexport function getRequiredShowcaseScenarios(\n entry: ComponentCatalogEntry,\n): readonly ShowcaseScenarioId[] {\n const activeSurfaces = ([\"web\", \"native\"] as const).filter((surface) =>\n isRendererMaturity(getComponentSurfaceStatus(entry, surface)),\n );\n if (activeSurfaces.length === 0) return plannedRequirements;\n\n const rendererScenarios = [...new Set(activeSurfaces.flatMap((surface) =>\n getRendererShowcaseScenarios(entry, surface),\n ))];\n return [\n \"contract\",\n ...rendererScenarios,\n ];\n}\n\nfunction isRendererMaturity(\n status: ComponentSurfaceStatus,\n): status is Extract<ComponentStatus, \"stable\" | \"beta\"> {\n return status === \"stable\" || status === \"beta\";\n}\n\n// These outputs expose no consumer-authored visible prose; default and accessibility proofs remain required.\nconst textlessComponentNames: ReadonlySet<string> = new Set([\n \"Icon\", \"IconButton\", \"Skeleton\", \"Spinner\", \"ThinkingOrb\", \"Divider\",\n \"Avatar\", \"Asset\", \"CounterBadge\", \"Image\", \"VisuallyHidden\", \"Pagination\",\n // These own form/range behavior but no long-form text slot; their child fields\n // and calendar cells own their copy, so duplicating that proof here misattributes it.\n \"Form\", \"DateRangePicker\",\n // 2026-10-18: Chart's category/series labels are short identifiers and its text alternative is a hidden\n // description for assistive technology; ImageChoiceGroup tiles carry accessible names, not visible copy.\n // Neither has a long-form text slot, so the long-copy proof would measure a product caption, not the component.\n \"Chart\", \"ImageChoiceGroup\",\n]);\n\n// These behaviors expose no interaction on either rendered surface.\nconst semanticOnlyBehaviors: ReadonlySet<NonNullable<ComponentCatalogEntry[\"behavior\"]>> = new Set([\n \"top\", \"authScreen\", \"heading\", \"bottomInfo\", \"nativePlatform\", \"textFormat\", \"asset\",\n]);\n\n// Keep surface capability lookup local: importing behaviorRegistry here would pull every\n// behavior contract into the lightweight showcase/evidence entry points. The alternative was\n// importing that registry; showcase.test.ts cross-checks these names against it to prevent drift.\nconst webKeyboardBehaviors: ReadonlySet<BehaviorName> = new Set([\n \"agreement\", \"alertDialog\", \"anchor\", \"authProviderButton\", \"bottomNavigation\", \"breadcrumb\",\n \"calendar\", \"carousel\", \"chart\", \"checkbox\", \"checkboxGroup\", \"chip\", \"collapsible\", \"combobox\",\n \"commandPalette\", \"contextMenu\", \"dataTable\", \"datePicker\", \"dateRange\", \"dialog\",\n \"disclosureGroup\", \"field\", \"filePicker\", \"floatingActionButton\", \"form\", \"layout\", \"link\",\n \"loadMore\", \"menu\", \"menubar\", \"numberField\", \"otpField\", \"pagination\", \"passwordField\",\n \"popover\", \"radioGroup\", \"searchField\", \"segmentedControl\", \"select\", \"sheet\", \"sidePanel\",\n \"sidebar\", \"skipNav\", \"slider\", \"splitter\", \"switch\", \"tabs\", \"tagsInput\", \"toast\",\n \"toggleGroup\", \"tooltip\", \"tour\", \"transferList\", \"tree\", \"uploadItem\",\n]);\nconst nativeActionBehaviors: ReadonlySet<BehaviorName> = new Set([\n \"agreement\", \"alertDialog\", \"authProviderButton\", \"bottomNavigation\", \"calendar\", \"carousel\",\n \"checkbox\", \"checkboxGroup\", \"chip\", \"collapsible\", \"combobox\", \"datePicker\", \"dateRange\",\n \"dialog\", \"disclosureGroup\", \"field\", \"filePicker\", \"floatingActionButton\", \"form\", \"link\",\n \"loadMore\", \"menu\", \"numberField\", \"otpField\", \"passwordField\", \"radioGroup\", \"searchField\",\n \"segmentedControl\", \"select\", \"sheet\", \"slider\", \"switch\", \"tabs\", \"tagsInput\", \"toast\",\n \"toggleGroup\", \"transferList\", \"uploadItem\",\n // 2026-10-14: Native DataTable sort/row actions and chart adjustable stepping.\n \"dataTable\", \"chart\",\n // 2026-10-18: Pagination became shared with a Native beta renderer (1bae9c1a); its page buttons declare the\n // activate action, so the Native surface owns a native-actions requirement like every other action behavior.\n \"pagination\",\n]);\n\nfunction getRendererShowcaseScenarios(\n entry: ComponentCatalogEntry,\n surface?: \"web\" | \"native\",\n): readonly Exclude<ShowcaseScenarioId, \"contract\">[] {\n const requirements: Exclude<ShowcaseScenarioId, \"contract\">[] = rendererRequirements.filter(\n (scenario) => scenario !== \"long-copy\" || !textlessComponentNames.has(entry.name),\n );\n // ColorPicker composes native form controls; its text commit/escape behavior still needs real keyboard proof.\n if (entry.name === \"ColorPicker\" && surface === \"web\") requirements.push(\"keyboard\");\n if (entry.behavior && !semanticOnlyBehaviors.has(entry.behavior)) {\n // Web owns DOM key bindings; Native declares host accessibility actions instead, so Pressable tests must not claim physical keyboard proof.\n if (surface === \"web\" && webKeyboardBehaviors.has(entry.behavior)) requirements.push(\"keyboard\");\n if (surface === \"native\" && nativeActionBehaviors.has(entry.behavior)) requirements.push(\"native-actions\");\n }\n return requirements;\n}\n\nexport function getRequiredShowcaseSurfaces(\n entry: ComponentCatalogEntry,\n): readonly ShowcaseSurface[] {\n return getRequiredShowcaseEvidence(entry).map(({ surface }) => surface);\n}\n\nexport function getRequiredShowcaseEvidence(\n entry: ComponentCatalogEntry,\n): readonly ShowcaseEvidenceRequirement[] {\n const requirements: ShowcaseEvidenceRequirement[] = [\n { surface: \"contract\", scenarios: [\"contract\"] },\n ];\n const activeSurfaces = ([\"web\", \"native\"] as const).filter((surface) =>\n isRendererMaturity(getComponentSurfaceStatus(entry, surface)),\n );\n for (const surface of activeSurfaces) {\n requirements.push({ surface, scenarios: getRendererShowcaseScenarios(entry, surface) });\n }\n return requirements;\n}\n\nexport function createShowcaseManifest(\n entries: readonly ComponentCatalogEntry[] = componentCatalog,\n): readonly ShowcaseComponentEntry[] {\n return entries.map((component) => ({\n storyId: getShowcaseStoryId(component),\n component,\n surfaceMaturity: {\n web: getComponentSurfaceStatus(component, \"web\"),\n native: getComponentSurfaceStatus(component, \"native\"),\n },\n requirements: getRequiredShowcaseEvidence(component),\n requiredScenarios: getRequiredShowcaseScenarios(component),\n requiredSurfaces: getRequiredShowcaseSurfaces(component),\n }));\n}\n\nexport const showcaseManifest = createShowcaseManifest();\n\nexport function createShowcaseCoverage(\n evidence: readonly ShowcaseEvidenceEntry[],\n manifest: readonly ShowcaseComponentEntry[] = showcaseManifest,\n): readonly ShowcaseCoverageEntry[] {\n return manifest.map(({ storyId, component, requirements }) => {\n const componentEvidence = evidence.filter((entry) => entry.storyId === storyId);\n const missingEvidence = requirements.flatMap(({ surface, scenarios }) =>\n scenarios\n .filter(\n (scenario) =>\n !componentEvidence.some(\n (entry) => entry.surface === surface && entry.scenarios.includes(scenario),\n ),\n )\n .map((scenario) => ({ surface, scenario })),\n );\n const missingSurfaces = [...new Set(missingEvidence.map(({ surface }) => surface))];\n const missingScenarios = [...new Set(missingEvidence.map(({ scenario }) => scenario))];\n return {\n storyId,\n component,\n missingEvidence,\n missingSurfaces,\n missingScenarios,\n complete: missingSurfaces.length === 0 && missingScenarios.length === 0,\n };\n });\n}\n\nexport function assertShowcaseCoverage(\n evidence: readonly ShowcaseEvidenceEntry[],\n manifest: readonly ShowcaseComponentEntry[] = showcaseManifest,\n): void {\n const missing = createShowcaseCoverage(evidence, manifest).filter(({ complete }) => !complete);\n if (missing.length === 0) return;\n const details = missing\n .map(({ storyId, missingEvidence }) =>\n `${storyId} (${missingEvidence.map(({ surface, scenario }) => `${surface}/${scenario}`).join(\", \") || \"none\"})`,\n )\n .join(\"\\n\");\n throw new Error(`Showcase evidence is incomplete:\\n${details}`);\n}\n\nexport function summarizeShowcaseMaturity(\n entries: readonly ComponentCatalogEntry[] = componentCatalog,\n): Readonly<Record<ComponentStatus, number>> {\n return entries.reduce<Record<ComponentStatus, number>>(\n (summary, entry) => {\n summary[entry.status] += 1;\n return summary;\n },\n { stable: 0, beta: 0, planned: 0, deprecated: 0 },\n );\n}\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.30.0\" as const;\n"]}
|
package/docs/architecture.md
CHANGED
|
@@ -75,6 +75,24 @@ recipe/behavior 배열, Web/Native별 status와 고정 documentation story ID를
|
|
|
75
75
|
평면 `componentCatalog`는 호환 view로 유지하며 renderer가 순차적으로 definition schema로
|
|
76
76
|
이동합니다.
|
|
77
77
|
|
|
78
|
+
## 등록 입력과 실행 증거
|
|
79
|
+
|
|
80
|
+
2026-10-18부터 `catalog.ts`의 한 행이 canonical 이름·안정성·지원 surface·한국어 `label`·공개 `companions`와
|
|
81
|
+
`extensions`를 소유한다. `id`는 기본 kebab 변환으로 얻되 이미 게시한 키가 다를 때만 재정의한다.
|
|
82
|
+
`componentIds`는 이 행에서 리터럴 타입을 유지하며 파생되고 `componentDefinitions`는 정규화한 view다.
|
|
83
|
+
이전에는 같은 등록 사실을 여덟 목록에서 관리해 22종 화면·구성 등록이 86개 파일 변경으로 번졌다.
|
|
84
|
+
|
|
85
|
+
공개 export 분석기는 이 행의 소유권을 실제 renderer exports와 합쳐 API 대응표와 renderer export index를 생성한다.
|
|
86
|
+
Renderer evidence는 활성 행·요구 시나리오·해당 index에서 기본 claim을 계산하고 별도 행동 proof만 명시한다.
|
|
87
|
+
등록이 테스트 통과를 뜻하지 않는다. default fixture·환경 매트릭스·행동 proof는 실제 renderer를 실행해야 한다.
|
|
88
|
+
지원하지 못한 시나리오는 gap으로 기록하며 stable 승격에서는 그 차이를 확인한다.
|
|
89
|
+
|
|
90
|
+
Showcase 이름·recipe·behavior 등록도 행을 소비하고 실행 예제는 별도로 작성한다. 정적 CSF가 필요한 개요·개별 항목은
|
|
91
|
+
기존 Storybook 도구의 `storybook:sync`로 생성하며 URL id와 고유 예제를 보존한다.
|
|
92
|
+
포트폴리오의 게시 catalog snapshot은 새 train의 `name`·`companions`·canonical `id`를 함께 보존한다.
|
|
93
|
+
소비 검사는 설치한 train의 snapshot으로 보조 심볼을 연결하고, optional extension에는 기본 API의 stable 상태를 상속하지 않는다.
|
|
94
|
+
기존 train의 id-only snapshot과 digest는 유지하며 그 train을 사용하는 동안만 과거 alias 해석을 유지한다.
|
|
95
|
+
|
|
78
96
|
## 플랫폼 분류
|
|
79
97
|
|
|
80
98
|
- `shared`: 같은 semantic API와 시각 계약을 Web/RN renderer가 각각 구현하는 목표
|
|
@@ -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.30.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
|
|
8
|
-
- Web renderer: stable
|
|
9
|
-
- Native renderer: stable
|
|
7
|
+
- Contract: stable 125 · beta 2
|
|
8
|
+
- Web renderer: stable 125 · beta 2
|
|
9
|
+
- Native renderer: stable 105 · beta 4 · unsupported 18
|
|
10
10
|
|
|
11
11
|
| Component | Canonical story ID | Contract | Web | Native | Documentation | Required evidence |
|
|
12
12
|
| --- | --- | --- | --- | --- | --- | --- |
|
|
@@ -43,7 +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,
|
|
46
|
+
| ImageChoiceGroup | `input/image-choice-group` | beta | beta | beta | generated only | contract: contract; web: default, dark, large-text, rtl, reduced-motion, accessibility; native: default, dark, large-text, rtl, reduced-motion, accessibility |
|
|
47
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 |
|
|
48
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 |
|
|
49
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 |
|
|
@@ -65,7 +65,7 @@ This document is the human-readable projection of the same catalog and Showcase
|
|
|
65
65
|
| Sidebar | `navigation/sidebar` | stable | stable | unsupported | [authored](../sidebar.md) | contract: contract; web: default, dark, long-copy, large-text, rtl, reduced-motion, accessibility, keyboard |
|
|
66
66
|
| BottomNavigation | `navigation/bottom-navigation` | stable | stable | stable | [authored](../bottom-navigation.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 |
|
|
67
67
|
| Breadcrumb | `navigation/breadcrumb` | stable | stable | unsupported | [authored](../breadcrumb.md) | contract: contract; web: default, dark, long-copy, large-text, rtl, reduced-motion, accessibility, keyboard |
|
|
68
|
-
| Pagination | `navigation/pagination` | stable | stable | beta | [authored](../pagination.md) | contract: contract; web: default, dark, large-text, rtl, reduced-motion, accessibility, keyboard; native: default, dark, large-text, rtl, reduced-motion, accessibility |
|
|
68
|
+
| Pagination | `navigation/pagination` | stable | stable | beta | [authored](../pagination.md) | contract: contract; web: default, dark, large-text, rtl, reduced-motion, accessibility, keyboard; native: default, dark, large-text, rtl, reduced-motion, accessibility, native-actions |
|
|
69
69
|
| LoadMore | `navigation/load-more` | stable | stable | stable | [authored](../load-more.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 |
|
|
70
70
|
| Steps | `navigation/steps` | stable | stable | stable | [authored](../steps.md) | contract: contract; web: default, dark, long-copy, large-text, rtl, reduced-motion, accessibility; native: default, dark, long-copy, large-text, rtl, reduced-motion, accessibility |
|
|
71
71
|
| Menubar | `navigation/menubar` | stable | stable | unsupported | [authored](../menubar.md) | contract: contract; web: default, dark, long-copy, large-text, rtl, reduced-motion, accessibility, keyboard |
|
|
@@ -85,7 +85,7 @@ This document is the human-readable projection of the same catalog and Showcase
|
|
|
85
85
|
| Statistic | `data-display/statistic` | stable | stable | stable | [authored](../statistic.md) | contract: contract; web: default, dark, long-copy, large-text, rtl, reduced-motion, accessibility; native: default, dark, long-copy, large-text, rtl, reduced-motion, accessibility |
|
|
86
86
|
| Timeline | `data-display/timeline` | stable | stable | stable | [authored](../timeline.md) | contract: contract; web: default, dark, long-copy, large-text, rtl, reduced-motion, accessibility; native: default, dark, long-copy, large-text, rtl, reduced-motion, accessibility |
|
|
87
87
|
| DataTable | `data-display/data-table` | stable | stable | beta | [authored](../data-table.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 |
|
|
88
|
-
| Chart | `data-display/chart` | beta | beta | beta | [authored](../chart.md) | contract: contract; web: default, dark,
|
|
88
|
+
| Chart | `data-display/chart` | beta | beta | beta | [authored](../chart.md) | contract: contract; web: default, dark, large-text, rtl, reduced-motion, accessibility, keyboard; native: default, dark, large-text, rtl, reduced-motion, accessibility, native-actions |
|
|
89
89
|
| Tree | `data-display/tree` | stable | stable | unsupported | [authored](../tree.md) | contract: contract; web: default, dark, long-copy, large-text, rtl, reduced-motion, accessibility, keyboard |
|
|
90
90
|
| Calendar | `data-display/calendar` | stable | stable | stable | [authored](../calendar.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 |
|
|
91
91
|
| Carousel | `data-display/carousel` | stable | stable | stable | [authored](../carousel.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 |
|
|
@@ -115,3 +115,25 @@ This document is the human-readable projection of the same catalog and Showcase
|
|
|
115
115
|
| DesignSystemProvider | `provider/design-system-provider` | stable | stable | stable | [authored](../design-system-provider.md) | contract: contract; web: default, dark, long-copy, large-text, rtl, reduced-motion, accessibility; native: default, dark, long-copy, large-text, rtl, reduced-motion, accessibility |
|
|
116
116
|
| SkipNav | `utility/skip-nav` | stable | stable | unsupported | [authored](../skip-nav.md) | contract: contract; web: default, dark, long-copy, large-text, rtl, reduced-motion, accessibility, keyboard |
|
|
117
117
|
| VisuallyHidden | `utility/visually-hidden` | stable | stable | unsupported | [authored](../visually-hidden.md) | contract: contract; web: default, dark, large-text, rtl, reduced-motion, accessibility |
|
|
118
|
+
| ScreenLayout | `layout/screen-layout` | stable | stable | stable | 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 |
|
|
119
|
+
| CompositionLayout | `layout/composition-layout` | stable | stable | stable | 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 |
|
|
120
|
+
| SettingsScreen | `layout/settings-screen` | stable | stable | stable | 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 |
|
|
121
|
+
| SearchScreen | `layout/search-screen` | stable | stable | stable | 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 |
|
|
122
|
+
| EditorScreen | `layout/editor-screen` | stable | stable | stable | 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 |
|
|
123
|
+
| PermissionScreen | `layout/permission-screen` | stable | stable | stable | 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 |
|
|
124
|
+
| OnboardingScreen | `layout/onboarding-screen` | stable | stable | stable | 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 |
|
|
125
|
+
| ModerationScreen | `layout/moderation-screen` | stable | stable | stable | 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 |
|
|
126
|
+
| ChatScreen | `layout/chat-screen` | stable | stable | stable | 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 |
|
|
127
|
+
| NotificationInboxScreen | `layout/notification-inbox-screen` | stable | stable | stable | 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 |
|
|
128
|
+
| CommentThreadScreen | `layout/comment-thread-screen` | stable | stable | stable | 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 |
|
|
129
|
+
| ListDetailScreen | `layout/list-detail-screen` | stable | stable | stable | 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 |
|
|
130
|
+
| MediaSelectionScreen | `layout/media-selection-screen` | stable | stable | stable | 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 |
|
|
131
|
+
| ProfileScreen | `layout/profile-screen` | stable | stable | stable | 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 |
|
|
132
|
+
| ChatMessage | `data-display/chat-message` | stable | stable | stable | 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 |
|
|
133
|
+
| NotificationRow | `data-display/notification-row` | stable | stable | stable | 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 |
|
|
134
|
+
| NotificationItem | `data-display/notification-item` | stable | stable | stable | 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 |
|
|
135
|
+
| CommentThreadRow | `data-display/comment-thread-row` | stable | stable | stable | 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 |
|
|
136
|
+
| ProfileSummary | `data-display/profile-summary` | stable | stable | stable | 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 |
|
|
137
|
+
| IconTile | `data-display/icon-tile` | stable | stable | stable | 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 |
|
|
138
|
+
| MessageComposer | `input/message-composer` | stable | stable | stable | 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 |
|
|
139
|
+
| PhotoSourceSheet | `overlay/photo-source-sheet` | stable | stable | stable | 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 |
|