@hjmds/design-contracts 1.42.0 → 1.43.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 CHANGED
@@ -9613,6 +9613,9 @@ export declare const recipeRegistry: {
9613
9613
  readonly bubbleRadius: 14;
9614
9614
  readonly bubblePaddingInline: 10;
9615
9615
  readonly bubblePaddingBlock: 6;
9616
+ readonly quoteRailWidth: 3;
9617
+ readonly quoteInset: 8;
9618
+ readonly quoteSurfaceOpacity: 0.12;
9616
9619
  readonly runGap: 6;
9617
9620
  readonly groupGap: 12;
9618
9621
  readonly tailWidth: 7;
@@ -1 +1 @@
1
- {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+GjB,CAAC;AAEX,MAAM,MAAM,UAAU,GAAG,MAAM,OAAO,cAAc,CAAC"}
1
+ {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+GjB,CAAC;AAEX,MAAM,MAAM,UAAU,GAAG,MAAM,OAAO,cAAc,CAAC"}
@@ -26,4 +26,29 @@ export type SearchResponse<T> = Readonly<{
26
26
  }>;
27
27
  }>[];
28
28
  }>;
29
+ /** Room data stays controlled: only the product can acknowledge persistence or grant permissions. */
30
+ export type ChatRoomProfileValue = Readonly<{
31
+ name: string;
32
+ description: string;
33
+ photoUrl: string | null;
34
+ }>;
35
+ export type ChatRoomMember = Readonly<{
36
+ id: string;
37
+ name: string;
38
+ detail?: string;
39
+ photoUrl?: string;
40
+ selected?: boolean;
41
+ disabled?: boolean;
42
+ }>;
43
+ export type ChatRoomConfirmation = Readonly<{
44
+ destructive?: boolean;
45
+ label: string;
46
+ title: string;
47
+ description: string;
48
+ confirmLabel: string;
49
+ cancelLabel: string;
50
+ errorLabel: string;
51
+ onConfirm: () => void | Promise<void>;
52
+ }>;
53
+ export declare function canSubmitChatRoom(profile: ChatRoomProfileValue, memberIds?: readonly string[]): boolean;
29
54
  //# sourceMappingURL=communication.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"communication.d.ts","sourceRoot":"","sources":["../src/communication.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,sBAAsB,GAAG,QAAQ,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AACzI,4FAA4F;AAC5F,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,SAAK;;;;;EAG9E;AACD,MAAM,MAAM,WAAW,GAAG,QAAQ,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AACpF,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,WAAW,GAAC,IAAI,GAAE,IAAI,CAEjE;AACD,MAAM,MAAM,cAAc,CAAC,CAAC,IAAI,QAAQ,CAAC;IAAE,MAAM,EAAE,CAAC,CAAC;IAAC,WAAW,EAAE,SAAS,QAAQ,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAA,KAAK,CAAC,EAAC,QAAQ,CAAC;YAAC,KAAK,EAAC,MAAM,CAAC;YAAA,GAAG,EAAC,MAAM,CAAA;SAAC,CAAC,CAAA;KAAC,CAAC,EAAE,CAAA;CAAE,CAAC,CAAC"}
1
+ {"version":3,"file":"communication.d.ts","sourceRoot":"","sources":["../src/communication.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,sBAAsB,GAAG,QAAQ,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AACzI,4FAA4F;AAC5F,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,SAAK;;;;;EAG9E;AACD,MAAM,MAAM,WAAW,GAAG,QAAQ,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AACpF,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,WAAW,GAAC,IAAI,GAAE,IAAI,CAEjE;AACD,MAAM,MAAM,cAAc,CAAC,CAAC,IAAI,QAAQ,CAAC;IAAE,MAAM,EAAE,CAAC,CAAC;IAAC,WAAW,EAAE,SAAS,QAAQ,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAA,KAAK,CAAC,EAAC,QAAQ,CAAC;YAAC,KAAK,EAAC,MAAM,CAAC;YAAA,GAAG,EAAC,MAAM,CAAA;SAAC,CAAC,CAAA;KAAC,CAAC,EAAE,CAAA;CAAE,CAAC,CAAC;AAEtJ,qGAAqG;AACrG,MAAM,MAAM,oBAAoB,GAAG,QAAQ,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAAC;AAC5G,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,CAAC;AAChJ,MAAM,MAAM,oBAAoB,GAAG,QAAQ,CAAC;IAAE,WAAW,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,CAAC,CAAC;AAChO,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,oBAAoB,EAAE,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAEvG"}
@@ -8,4 +8,7 @@ export function validateReplyTarget(target) {
8
8
  if (target !== null && !target.id.trim())
9
9
  throw new TypeError("Reply target requires the actual message ID");
10
10
  }
11
+ export function canSubmitChatRoom(profile, memberIds) {
12
+ return profile.name.trim().length > 0 && (memberIds === undefined || (memberIds.length > 0 && memberIds.every(id => id.trim().length > 0) && new Set(memberIds).size === memberIds.length));
13
+ }
11
14
  //# sourceMappingURL=communication.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"communication.js","sourceRoot":"","sources":["../src/communication.ts"],"names":[],"mappings":"AACA,4FAA4F;AAC5F,MAAM,UAAU,oBAAoB,CAAC,KAAa,EAAE,GAAW,EAAE,SAAS,GAAG,EAAE;IAC9E,IAAG,CAAC,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,IAAE,GAAG,IAAE,CAAC,IAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAE,SAAS,GAAC,CAAC,IAAE,SAAS,GAAC,CAAC;QAAC,MAAM,IAAI,UAAU,CAAC,wDAAwD,CAAC,CAAC;IAC5K,OAAO,EAAE,IAAI,EAAC,KAAK,CAAC,MAAM,EAAC,GAAG,EAAC,IAAI,EAAC,KAAK,CAAC,MAAM,GAAC,GAAG,IAAE,SAAS,EAAC,QAAQ,EAAC,KAAK,CAAC,MAAM,GAAC,GAAG,EAAE,CAAC;AAC7F,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,MAAwB;IAC3D,IAAG,MAAM,KAAG,IAAI,IAAE,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE;QAAC,MAAM,IAAI,SAAS,CAAC,6CAA6C,CAAC,CAAC;AACxG,CAAC","sourcesContent":["export type ComposerLengthFeedback = Readonly<{ label: string; formatCount: (used: number, max: number) => string; threshold?: number }>;\n/** Match the controlled text/maxLength UTF-16 unit; do not silently trim a user's draft. */\nexport function resolveComposerLimit(value: string, max: number, threshold = .8) {\n if(!Number.isSafeInteger(max)||max<=0||!Number.isFinite(threshold)||threshold<0||threshold>1)throw new RangeError(\"Composer limit must be positive and threshold in [0,1]\");\n return { used:value.length,max,near:value.length/max>=threshold,exceeded:value.length>max };\n}\nexport type ReplyTarget = Readonly<{ id: string; author: string; excerpt: string }>;\nexport function validateReplyTarget(target: ReplyTarget|null):void {\n if(target!==null&&!target.id.trim())throw new TypeError(\"Reply target requires the actual message ID\");\n}\nexport type SearchResponse<T> = Readonly<{ result: T; suggestions: readonly Readonly<{query: string;match?:Readonly<{start:number;end:number}>}>[] }>;\n"]}
1
+ {"version":3,"file":"communication.js","sourceRoot":"","sources":["../src/communication.ts"],"names":[],"mappings":"AACA,4FAA4F;AAC5F,MAAM,UAAU,oBAAoB,CAAC,KAAa,EAAE,GAAW,EAAE,SAAS,GAAG,EAAE;IAC9E,IAAG,CAAC,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,IAAE,GAAG,IAAE,CAAC,IAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAE,SAAS,GAAC,CAAC,IAAE,SAAS,GAAC,CAAC;QAAC,MAAM,IAAI,UAAU,CAAC,wDAAwD,CAAC,CAAC;IAC5K,OAAO,EAAE,IAAI,EAAC,KAAK,CAAC,MAAM,EAAC,GAAG,EAAC,IAAI,EAAC,KAAK,CAAC,MAAM,GAAC,GAAG,IAAE,SAAS,EAAC,QAAQ,EAAC,KAAK,CAAC,MAAM,GAAC,GAAG,EAAE,CAAC;AAC7F,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,MAAwB;IAC3D,IAAG,MAAM,KAAG,IAAI,IAAE,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE;QAAC,MAAM,IAAI,SAAS,CAAC,6CAA6C,CAAC,CAAC;AACxG,CAAC;AAOD,MAAM,UAAU,iBAAiB,CAAC,OAA6B,EAAE,SAA6B;IAC7F,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,SAAS,KAAK,SAAS,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,IAAI,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;AAC7L,CAAC","sourcesContent":["export type ComposerLengthFeedback = Readonly<{ label: string; formatCount: (used: number, max: number) => string; threshold?: number }>;\n/** Match the controlled text/maxLength UTF-16 unit; do not silently trim a user's draft. */\nexport function resolveComposerLimit(value: string, max: number, threshold = .8) {\n if(!Number.isSafeInteger(max)||max<=0||!Number.isFinite(threshold)||threshold<0||threshold>1)throw new RangeError(\"Composer limit must be positive and threshold in [0,1]\");\n return { used:value.length,max,near:value.length/max>=threshold,exceeded:value.length>max };\n}\nexport type ReplyTarget = Readonly<{ id: string; author: string; excerpt: string }>;\nexport function validateReplyTarget(target: ReplyTarget|null):void {\n if(target!==null&&!target.id.trim())throw new TypeError(\"Reply target requires the actual message ID\");\n}\nexport type SearchResponse<T> = Readonly<{ result: T; suggestions: readonly Readonly<{query: string;match?:Readonly<{start:number;end:number}>}>[] }>;\n\n/** Room data stays controlled: only the product can acknowledge persistence or grant permissions. */\nexport type ChatRoomProfileValue = Readonly<{ name: string; description: string; photoUrl: string | null }>;\nexport type ChatRoomMember = Readonly<{ id: string; name: string; detail?: string; photoUrl?: string; selected?: boolean; disabled?: boolean }>;\nexport type ChatRoomConfirmation = Readonly<{ destructive?: boolean; label: string; title: string; description: string; confirmLabel: string; cancelLabel: string; errorLabel: string; onConfirm: () => void | Promise<void> }>;\nexport function canSubmitChatRoom(profile: ChatRoomProfileValue, memberIds?: readonly string[]): boolean {\n return profile.name.trim().length > 0 && (memberIds === undefined || (memberIds.length > 0 && memberIds.every(id => id.trim().length > 0) && new Set(memberIds).size === memberIds.length));\n}\n"]}
@@ -265,6 +265,9 @@ export declare const chatMessageRecipe: {
265
265
  readonly bubbleRadius: 14;
266
266
  readonly bubblePaddingInline: 10;
267
267
  readonly bubblePaddingBlock: 6;
268
+ readonly quoteRailWidth: 3;
269
+ readonly quoteInset: 8;
270
+ readonly quoteSurfaceOpacity: 0.12;
268
271
  readonly runGap: 6;
269
272
  readonly groupGap: 12;
270
273
  readonly tailWidth: 7;
@@ -1 +1 @@
1
- {"version":3,"file":"screen-patterns.d.ts","sourceRoot":"","sources":["../src/screen-patterns.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"screen-patterns.d.ts","sourceRoot":"","sources":["../src/screen-patterns.ts"],"names":[],"mappings":"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"}
@@ -199,6 +199,10 @@ export const chatMessageRecipe = {
199
199
  bubbleRadius: 14,
200
200
  bubblePaddingInline: 10,
201
201
  bubblePaddingBlock: 6,
202
+ // 2026-10-23: Telegram-style quote rail remains visible inside both neutral and filled brand bubbles.
203
+ quoteRailWidth: 3,
204
+ quoteInset: spacing.xs,
205
+ quoteSurfaceOpacity: 0.12,
202
206
  // Bubbles of one run read as a stack; a new author or minute starts a visibly separate group.
203
207
  runGap: 6,
204
208
  groupGap: spacing.sm,
@@ -1 +1 @@
1
- {"version":3,"file":"screen-patterns.js","sourceRoot":"","sources":["../src/screen-patterns.ts"],"names":[],"mappings":"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","sourcesContent":["import { control, glyph, layout, opacity, radius, spacing } from \"./foundations.js\";\nimport { avatarRecipe, emptyStateRecipe, spinnerRecipe, type CornerAccessoryPlacement } from \"./component-recipes.js\";\nimport { semanticColors } from \"./semantic-colors.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 // 2026-10-18: empty copy stays at the 14pt body size, including full-screen compositions.\n titleVariant: state.kind === \"empty\" ? emptyStateRecipe.title.textVariant : \"title\",\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 * `body-bleed`: header, notice and footer keep the shell padding; the body has no gutter on any side, so a map or\n * canvas meets the header (or notice), the screen edges and the footer. With no footer the body is still the last\n * region and clears the bottom insets the screen owns (`safeAreaBottom`, an overlay BottomNavigation) without the\n * gutter. choose-window's map screens used `body-edge` and kept a 16pt strip above and below the map (2026-10-18).\n */\nexport type ScreenContentInset = \"default\" | \"none\" | \"body-edge\" | \"body-bleed\";\nexport const screenContentInsets = [\"default\", \"none\", \"body-edge\", \"body-bleed\"] as const satisfies readonly ScreenContentInset[];\n\n/**\n * 2026-10-18 사용자 지시: 입력 자동 포커스는 페이지 진입에만 적용하고 하단 시트에서는 폐지한다.\n * 페이지는 `first-input`으로 명시한 주 입력 또는 첫 유효 입력을 한 번 고른다. 하단 시트는 renderer의\n * 상속 경계에서 중첩 화면까지 자동 포커스를 막는다. Dialog·측면 시트의 모달 포커스 계약은 유지한다.\n * `single-input`은 Dialog·측면 시트의 단일 입력 선택, `none`은 입력 자동 선택을 끈다.\n * 비활성·읽기 전용·initialFocusTarget={false} 칸은 제외한다. 이미 포커스된 입력을 빼앗지 않으며\n * 화면은 mount당 한 번만 포커스한다. 모션 감소는 포커스 정책을 바꾸지 않는다.\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 // 2026-10-18: input focus belongs to page entry, including chat/auth pages; bottom sheets opt out at their boundary.\n screen: \"first-input\",\n search: \"first-input\",\n editor: \"first-input\",\n chat: \"first-input\",\n commentThread: \"first-input\",\n overlay: \"single-input\",\n auth: \"first-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/**\n * 진입 포커스 창(2026-10-18 1.28.1 앱 채택 점검). mount 시점 한 번만 고르면 세 경우가 앱 우회로 남았다: 진입 때 열린\n * 모달 아래 칸(번뚝 첫 가입 약관), 진입 중 비동기로 나타나는 칸(번뚝 계정 삭제 확인), 사용자 행동으로 나중에 나타나는 칸\n * (utilverse 검색 열기, 번뚝 아이디어 시트·spint 작성 단계). 그래서 범위는 아래 상태를 가진다.\n *\n * - `entering`: 진입 중(Native 전환·시트 등장 interaction 전). 칸 등록만 받는다.\n * - `open`: 진입이 끝났지만 아직 포커스하지 못했다. 칸이 새로 등록되거나 위 오버레이가 닫히면 다시 고른다. 모달 아래에서\n * 진입한 화면은 모달이 닫힐 때 사용자가 그 화면을 아직 만지지 않았으면 그때 포커스한다.\n * - `settled`: 포커스했거나, 사용자가 범위를 직접 조작(터치·포인터·키·휠)했거나, 이미 다른 텍스트 칸에 초점이 있다.\n * 이후에 입력이 새로 나타나도 자동 포커스를 다시 시작하지 않는다(2026-10-18 페이지 진입에만 적용).\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 // Page entry only: revealing a marked field after interaction/entry must not open the keyboard again.\n return 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 // Full-screen reading routes use fixed travel, unlike a Sheet's fraction of its own height.\n // Migrated from Diairy's handle/top-bounce contract so products no longer own dismissal physics.\n pullDismiss: {\n activationDistance: 6,\n distance: 80,\n flickDistance: 32,\n flickVelocity: 0.65,\n maxOffset: 160,\n settleDuration: 140,\n topTolerance: 1,\n },\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 /**\n * In-place room CompositionLayout's loading/empty/error/restricted replacement keeps (`stateHeight`), so the state\n * centers inside a section that has no parent height. 2026-10-23 audit: Yajalal wrapped 13+ layouts in\n * `<View style={{ minHeight: N }}>` + `layoutStyle={{ flex: 1 }}` with 36–220. The steps follow those values:\n * `compact` 96 (rails, inline save errors, share-card rows: 68–96), `regular` 160 (a list/table section's body:\n * 120–180), `large` 220 (a field or chart panel). `fit` keeps the state's own height (an inline loading line).\n * Ready content is never stretched by this floor.\n */\n compositionState: { minHeight: { fit: null, compact: 96, regular: 160, large: 220 } },\n /**\n * Pull to refresh (Native ScreenLayout `onRefresh`). Without a product `loadingIndicator` the system control spins in\n * the shared brand spinner tone on the surface plate. With one, the system control stays for the gesture but is\n * drawn transparent and the product visual sits `indicatorOffset` below the body top, centered, while `refreshing`.\n * 2026-10-23: spint Home, Notifications and Cell each set `tintColor=\"transparent\"` and put FlowerSpinner in a list\n * header by hand.\n */\n refresh: { tint: spinnerRecipe.tones.brand, background: semanticColors.surface.default, indicatorOffset: spacing.md },\n} as const;\n\nexport type CompositionStateHeight = keyof typeof screenPatternRecipe.compositionState.minHeight;\nexport function resolveCompositionStateMinHeight(height: CompositionStateHeight = \"fit\"): number | null {\n if (!Object.hasOwn(screenPatternRecipe.compositionState.minHeight, height)) {\n throw new TypeError(`Unsupported CompositionLayout stateHeight: ${String(height)}`);\n }\n return screenPatternRecipe.compositionState.minHeight[height];\n}\n\n/**\n * Native host outside the screens: window safe-area insets and the canvas behind them. 2026-10-23 audit: choose-window\n * (`app/_layout.tsx` AppCanvas), Unairplane (`ui/index.tsx` AppScreenHost, FlightLookupScreen, BoardingPassScanner)\n * each wrapped routes in `SafeAreaView edges={[\"top\",\"left\",\"right\"]}` painted `colors.bg`, because ScreenLayout only\n * took top/bottom numbers and its root stops at the reading width, so the window background showed in the notch and\n * beside the column. The bottom stays out of the default: ScreenLayout `safeAreaBottom` pads the last region\n * max(gutter, inset) once, and a host bottom inset would add the gutter on top of it.\n */\nexport type ScreenHostEdge = \"top\" | \"right\" | \"bottom\" | \"left\";\nexport type ScreenHostSurface = \"default\" | \"transparent\";\nexport const screenHostDefaults = { edges: [\"top\", \"right\", \"left\"], surface: \"default\" } as const satisfies {\n edges: readonly ScreenHostEdge[];\n surface: ScreenHostSurface;\n};\nconst screenHostEdges: readonly ScreenHostEdge[] = [\"top\", \"right\", \"bottom\", \"left\"];\n\n/** Padding a ScreenHost applies from window insets; edges outside the list stay 0. */\nexport function resolveScreenHostInsets(\n edges: readonly ScreenHostEdge[],\n insets: Readonly<Partial<Record<ScreenHostEdge, number>>>,\n): Readonly<Record<ScreenHostEdge, number>> {\n const seen = new Set<ScreenHostEdge>();\n for (const edge of edges) {\n if (!screenHostEdges.includes(edge)) throw new TypeError(`Unsupported ScreenHost edge: ${String(edge)}`);\n if (seen.has(edge)) throw new TypeError(`Duplicate ScreenHost edge: ${edge}`);\n seen.add(edge);\n }\n const padding = { top: 0, right: 0, bottom: 0, left: 0 };\n for (const edge of seen) {\n const value = insets[edge] ?? 0;\n if (!Number.isFinite(value) || value < 0) throw new RangeError(`ScreenHost ${edge} inset must be non-negative`);\n padding[edge] = value;\n }\n return padding;\n}\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 /** Counters can align to the field end; validation errors retain their normal alignment. */\n descriptionAlign?: \"start\" | \"end\";\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 // The supplied reference keeps the tip on the top edge and curves its underside into the bubble (2026-10-20).\n // Add tailCornerRadius to the drawn width so the tail overlaps the rounded bubble corner without a gap.\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 /**\n * Reaction summary pill beside the time (2026-10-18 BurnTok DM): one button that opens the same hold menu.\n * Counts below `minCount` show the emoji alone, as the measured DM references do for a single reaction.\n */\n reactionSummary: { minHeight: 24, paddingInline: spacing.xs, itemGap: spacing.xxs, emojiGap: 2, minCount: 2 },\n} as const;\n\nexport type ChatReactionSummaryItem = Readonly<{ id: string; emoji: string; count: number }>;\nexport type ChatReactionSummary = Readonly<{\n label: string;\n items: readonly ChatReactionSummaryItem[];\n /**\n * Counts only, for readers who cannot react (2026-10-18 Utilverse guests): drawn in the same place beside the time\n * as non-interactive text named by `label`, without the pill surface, so it does not look or act like a control.\n * Default `false` (the pill button that opens the hold menu).\n */\n readOnly?: boolean;\n}>;\n/**\n * Validates ChatMessage `reactions.summary` and marks which counts are drawn. The label (the button's accessible name)\n * is required; ids are unique and non-empty, emoji non-empty and counts positive integers; a count below\n * `reactionSummary.minCount` shows the emoji alone.\n */\nexport function resolveChatReactionSummary({ label, items }: ChatReactionSummary): readonly (ChatReactionSummaryItem & Readonly<{ showCount: boolean }>)[] {\n if (!label.trim()) throw new TypeError(\"Reaction summary requires a localized label\");\n const ids = new Set<string>();\n return items.map(item => {\n if (!item.id.trim() || ids.has(item.id)) throw new TypeError(\"Reaction summary ids must be unique and non-empty\");\n if (!item.emoji.trim()) throw new TypeError(\"Reaction summary items require an emoji\");\n if (!Number.isSafeInteger(item.count) || item.count < 1) throw new RangeError(\"Reaction summary counts must be positive integers\");\n ids.add(item.id);\n return { ...item, showCount: item.count >= chatMessageRecipe.reactionSummary.minCount };\n });\n}\n\n/**\n * \"Someone is typing\" row in a chat timeline (2026-10-18 BurnTok DM). It reuses the incoming bubble geometry\n * (chatMessageRecipe) so it reads as the next incoming message; only the dots are its own values. Under reduced\n * motion the dots stay at full opacity instead of pulsing.\n */\nexport const typingIndicatorRecipe = {\n dotSize: 6,\n dotGap: spacing.xxs,\n /** One pulse of the three dots; each dot starts `staggerMs` after the previous one. */\n cycleMs: 1200,\n staggerMs: 160,\n restOpacity: 0.35,\n} as const;\n\n/**\n * Centered date (or time) row between timeline groups (2026-10-18 Utilverse chat, which drew it as a product\n * caption). The next message still owns its own group gap above it, so this row only adds the space before it.\n */\nexport const chatDateSeparatorRecipe = {\n paddingTop: spacing.sm,\n paddingBottom: spacing.xxs,\n textVariant: \"caption\",\n tone: \"muted\",\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 * Paged photo album for ChatMessage `mediaAlbum` and CommentThreadItem `mediaAlbum` (2026-10-18, Utilverse social\n * photos). Only the shown page is rendered, so a product that authorizes each image can fetch one photo at a time\n * instead of every photo in a timeline row. The counter row matches CarouselMotion `navigation=\"counter\"`:\n * previous icon · position · next icon under the page; the frame keeps the host's media width and radius.\n */\nexport const mediaAlbumRecipe = {\n /** Page frame width / height when the product gives no aspect ratio. */\n defaultAspectRatio: 1,\n /** Space between the page frame and the counter row. */\n controlGap: spacing.xxs,\n /** Previous/next are small ghost IconButtons so the counter row stays compact beside thumbnails. */\n controlSize: \"small\",\n controlGlyphSize: glyph.sm,\n /**\n * Loading / failed page drawn by `MediaAlbumPageStatus` (2026-10-18 Utilverse: the page frame was one accessible\n * image, so the loading text and retry button inside it were unreachable by screen readers). The status block is\n * centered in the frame (VQ-09); retry is a small secondary Button.\n */\n pageStatus: { gap: spacing.xs, padding: spacing.sm, textVariant: \"caption\", retryTone: \"secondary\", retrySize: \"small\" },\n} as const;\n\nexport type MediaAlbumPageStatusKind = \"loading\" | \"error\";\n/** A page status names what the reader is waiting for or what failed; the label is the only copy. */\nexport function validateMediaAlbumPageStatus(kind: MediaAlbumPageStatusKind, label: string): void {\n if (kind !== \"loading\" && kind !== \"error\") throw new TypeError(\"Media album page status must be loading or error\");\n if (!label.trim()) throw new TypeError(\"Media album page status requires a localized label\");\n}\n\n/** A controlled index outside the set is a contract error, like Carousel's unknown `currentKey`. */\nexport function validateMediaAlbum(count: number, index: number): void {\n if (!Number.isSafeInteger(count) || count < 1) throw new RangeError(\"Media album requires at least one page\");\n if (!Number.isSafeInteger(index) || index < 0 || index >= count) throw new RangeError(\"Media album index must point at an existing page\");\n}\n\n/** One message or comment carries one photo set: either the eager `media` previews or the paged `mediaAlbum`. */\nexport function validateMediaSetChoice(hasMedia: boolean, hasAlbum: boolean): void {\n if (hasMedia && hasAlbum) throw new TypeError(\"Pass either media or mediaAlbum, not both\");\n}\n\n/** Uncontrolled albums keep the nearest page when the product's photo set shrinks (moderation, deletion). */\nexport function resolveMediaAlbumIndex(count: number, index: number): number {\n if (!Number.isSafeInteger(count) || count < 1) throw new RangeError(\"Media album requires at least one page\");\n return Math.min(Math.max(0, Math.trunc(index)), count - 1);\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}\n/** Footer slot of PermissionScreen in display order. */\nexport type PermissionFooterSlot = \"primary\" | \"recheck\" | \"alternative\" | \"skip\";\n/** Button emphasis per slot: one filled primary, framed same-width secondaries, a quiet skip last. */\nexport type PermissionFooterEmphasis = \"primary\" | \"secondary\" | \"ghost\";\n/**\n * Footer order and hierarchy (2026-10-23). Unairplane's boarding-pass scanner put \"check again\" and \"choose a photo\"\n * as Buttons inside `explanation` because the footer had only primary + skip, so their order, width and emphasis\n * differed from the footer. HJM now owns them:\n * 1. primary — request / settings / continue from `resolvePermissionAction`;\n * 2. recheck — re-read the OS permission after the user returns from settings; only while `denied`;\n * 3. alternative — a path that works without the permission (pick a photo, type it in); hidden once `granted`,\n * where the screen only continues;\n * 4. skip — leave the feature (ghost, last), unchanged.\n * Secondaries are framed and full width like the primary (SELECTION 보조 행동: 주 행동 아래 같은 폭 secondary).\n */\nexport function resolvePermissionFooter(\n status: PermissionScreenStatus,\n supplied: Readonly<{ recheck: boolean; alternative: boolean; skip: boolean }>,\n): readonly Readonly<{ slot: PermissionFooterSlot; emphasis: PermissionFooterEmphasis }>[] {\n const footer: { slot: PermissionFooterSlot; emphasis: PermissionFooterEmphasis }[] = [];\n if (resolvePermissionAction(status) !== null) footer.push({ slot: \"primary\", emphasis: \"primary\" });\n if (supplied.recheck && status === \"denied\") footer.push({ slot: \"recheck\", emphasis: \"secondary\" });\n if (supplied.alternative && status !== \"granted\") footer.push({ slot: \"alternative\", emphasis: \"secondary\" });\n if (supplied.skip) footer.push({ slot: \"skip\", emphasis: \"ghost\" });\n return footer;\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 // 2026-10-20 Spint feedback: separate comment blocks and identity/body/action lines for readability.\n lineGap: spacing.xxs,\n rowGap: spacing.lg,\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 // Inline per-comment panel (edit/report/block form) under the action row (2026-10-18, Utilverse): a form reads as its\n // own block, so it sits a full spacing step below the reply line instead of the compact line gap.\n panelGap: spacing.xs,\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 * What the SearchScreen filter rail does to a result. `narrow` (default) only removes results, so with nothing applied\n * a zero result is the query's and no filter can bring results back. `scope` chooses what is searched (keyword vs\n * address, region, map area): changing it can turn a zero into results even with nothing applied (2026-10-18:\n * choose-window's keyword/address switch is the recovery for a zero result, so it skipped resultSummary entirely).\n */\nexport type SearchFiltersRole = \"narrow\" | \"scope\";\nexport const searchFiltersRoles = [\"narrow\", \"scope\"] as const satisfies readonly SearchFiltersRole[];\n/**\n * Whether SearchScreen shows its filter rail (`filters` and the filter sheet trigger). Two-step search shows it only\n * beside results so typing keeps the pinned area short. A query-caused zero hides it only when the filters narrow,\n * because then none of them can fix the zero; scope filters stay as the recovery path. A filter-caused zero always keeps\n * it so the cause can be undone. Both renderers call this so the rule cannot drift between platforms.\n */\nexport function resolveSearchFilterRailVisible(phase: SearchScreenPhase, twoStep: boolean, cause: SearchEmptyCause, role: SearchFiltersRole = \"narrow\"): boolean {\n if (!searchFiltersRoles.includes(role)) throw new RangeError(\"SearchScreen filtersRole must be narrow or scope\");\n if (twoStep && phase !== \"results\") return false;\n return cause !== \"query\" || role === \"scope\";\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. */\nconst notificationRowGeometry = {\n gap: 12, contentGap: 4, avatarSize: 44, avatarBadgeSize: 20,\n thumbnailSize: 44, unreadSize: 6, previewLines: 2, paddingBlock: 12, paddingInline: 16,\n} as const;\nexport const notificationRowRecipe = {\n ...notificationRowGeometry,\n // Virtualized inboxes provide the section boundary; the shared row owns the text-aligned separator.\n separatorInsetStart: notificationRowGeometry.paddingInline + notificationRowGeometry.avatarSize + notificationRowGeometry.gap,\n interaction: { disabledOpacity: opacity.disabled, pressedOpacity: opacity.pressed },\n} as const;\n\n/** Shared profile identity geometry; product owns the avatar content. */\nexport const profileSummaryRecipe = Object.freeze({\n avatarSize: 72,\n avatarGlyphSize: glyph.xxl,\n actionsLayouts: Object.freeze({\n inline: Object.freeze({ axis: \"inline\", gap: \"xs\" } as const),\n stacked: Object.freeze({ axis: \"block\", gap: \"xs\" } as const),\n }),\n /**\n * ProfileScreen `editPlacement=\"summary\"` draws the edit action first in the summary's action row. A framed small\n * button reads as the card's own action; the below-summary placement keeps its ghost button (2026-10-15 utilverse\n * account decision: the edit action belongs inside the profile card).\n */\n editAction: Object.freeze({ tone: \"secondary\", size: \"small\" } as const),\n});\n\n/** Launcher artwork stays above its caption; product overlays may extend beyond the icon frame. */\n/**\n * Frame of an IconTile icon (2026-10-18 Utilverse launcher). `surface` draws the shared filled, hairlined frame;\n * `none` leaves product artwork that is already a complete launcher icon unframed. `shape` follows the product's\n * icon theme (squircle on iPhone shells, square on Windows/Linux shells); `size: \"fill\"` lets the icon span its\n * grid cell between `fillMinSize` and `fillMaxSize` instead of a product computing the cell size.\n */\nexport type IconTileFrame = \"surface\" | \"none\";\nexport type IconTileShape = \"squircle\" | \"square\" | \"circle\";\nexport type IconTileSize = \"fixed\" | \"fill\";\nexport const iconTileRecipe = Object.freeze({ iconSize: 64, labelMaxWidth: 72, multilineLabelMaxWidth: 84, multilineLabelMinHeight: 44, ghostOpacity: 0.55, gap: 6, iconRadius: \"22%\",\n /** Corner radius as a fraction of the icon size; `squircle` keeps the original 22%. */\n shapes: Object.freeze({ squircle: 0.22, square: 0, circle: 0.5 }) as Readonly<Record<IconTileShape, number>>,\n // Standalone tile activation must not add Button face padding around a narrow launcher cell.\n activation: Object.freeze({ minimumTarget: control.minTouchTarget, pressedOpacity: opacity.pressed, disabledOpacity: opacity.disabled }),\n fillMinSize: 48, fillMaxSize: 68,\n /**\n * `locked`: the tile stays pressable so the product can explain why (sign-in required), drawn at the disabled\n * opacity, and its name gains the product's `lockedLabel`. Utilverse ToolboxScreen dimmed an outer View with\n * activation.disabledOpacity and put the lock badge at `right: -4, top: -4` (2026-10-23); the corner accessory keeps\n * full opacity so the reason mark stays legible.\n */\n locked: Object.freeze({ opacity: opacity.disabled }),\n /** Corner mark on the icon frame; `offset` is the outward overhang (Asset/Avatar meaning), spacing.xxs 4. */\n accessory: Object.freeze({ offset: spacing.xxs }),\n defaults: Object.freeze({ frame: \"surface\" as IconTileFrame, shape: \"squircle\" as IconTileShape, size: \"fixed\" as IconTileSize, accessoryPlacement: \"top-end\" as CornerAccessoryPlacement }) });\n\n/**\n * What an IconTile passes to an `icon` render function: the rendered icon edge (`iconSize` for `fixed`, the measured\n * cell-clamped edge for `fill`). Fixed-size artwork (images, generated launcher art) sizes itself from it; Utilverse\n * re-computed the 48–68 clamp from its grid width to size its artwork (2026-10-18).\n */\nexport type IconTileArtwork = Readonly<{ edge: number }>;\n\n/** The edge a `size=\"fill\"` icon takes in a cell of `cellWidth`, for layout estimates made before the tile measures. */\nexport function resolveIconTileFillEdge(cellWidth: number): number {\n if (!Number.isFinite(cellWidth) || cellWidth < 0) throw new RangeError(\"IconTile cell width must be a non-negative finite number\");\n return Math.min(iconTileRecipe.fillMaxSize, Math.max(iconTileRecipe.fillMinSize, cellWidth));\n}\n"]}
1
+ {"version":3,"file":"screen-patterns.js","sourceRoot":"","sources":["../src/screen-patterns.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AACpF,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,aAAa,EAAiC,MAAM,wBAAwB,CAAC;AACtH,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAQtD,MAAM,UAAU,yBAAyB,CAAC,QAA4B,EAAE,IAAI,EAAE,OAAO,EAAE;IACrF,IAAI,CAAC,CAAC,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/E,MAAM,IAAI,SAAS,CAAC,8BAA8B,CAAC,CAAC;IACtD,CAAC;IACD,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;QAClD,MAAM,IAAI,SAAS,CAAC,yCAAyC,CAAC,CAAC;IACjE,CAAC;IACD,OAAO;QACL,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,eAAe,EAAE,KAAK,CAAC,IAAI,KAAK,OAAO;QACvC,IAAI,EAAE,KAAK,CAAC,IAAI,KAAK,SAAS;QAC9B,0FAA0F;QAC1F,YAAY,EAAE,KAAK,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO;QACnF,YAAY,EAAE,KAAK,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ;KACrD,CAAC;AACb,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,SAAS,EAAE,EAAE;IACb,eAAe,EAAE,OAAO,CAAC,GAAG;IAC5B,gBAAgB,EAAE,EAAE;IACpB,sBAAsB,EAAE,CAAC;IACzB,cAAc,EAAE,OAAO,CAAC,GAAG;IAC3B;;;OAGG;IACH,UAAU,EAAE,QAAQ;IACpB,kBAAkB,EAAE,QAAQ;CACpB,CAAC;AAQX,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,gHAAgH;IAChH,WAAW,EAAE,EAAE;IACf,SAAS,EAAE,EAAE;IACb,MAAM,EAAE,CAAC;CACD,CAAC;AACX,MAAM,UAAU,kBAAkB,CAAC,IAA+C,EAAE,UAAmB;IACrG,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO;QAAE,MAAM,IAAI,SAAS,CAAC,wCAAwC,CAAC,CAAC;IACjH,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE;QAAE,MAAM,IAAI,SAAS,CAAC,gDAAgD,CAAC,CAAC;IAC9F,IAAI,UAAU;QAAE,MAAM,IAAI,SAAS,CAAC,6DAA6D,CAAC,CAAC;AACrG,CAAC;AAcD,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,CAAkD,CAAC;AAqBnI,oFAAoF;AACpF,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,qHAAqH;IACrH,MAAM,EAAE,aAAa;IACrB,MAAM,EAAE,aAAa;IACrB,MAAM,EAAE,aAAa;IACrB,IAAI,EAAE,aAAa;IACnB,aAAa,EAAE,aAAa;IAC5B,OAAO,EAAE,cAAc;IACvB,IAAI,EAAE,aAAa;CACgC,CAAC;AAEtD,MAAM,UAAU,yBAAyB,CAAkC,UAAwB,EAAE,IAAsB;IACzH,IAAI,IAAI,KAAK,MAAM;QAAE,OAAO,IAAI,CAAC;IACjC,MAAM,OAAO,GAAG,CAAC,GAAG,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;IAClE,IAAI,IAAI,KAAK,cAAc,EAAE,CAAC;QAC5B,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QACvD,OAAO,IAAI,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,UAAU,KAAK,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IAC3E,CAAC;IACD,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,SAAS,CAAC,SAAS,IAAI,SAAS,CAAC,UAAU,KAAK,KAAK,CAAC,CAAC;IACpG,OAAO,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,SAAS,CAAC,UAAU,KAAK,IAAI,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;AAC1F,CAAC;AAyCD,MAAM,UAAU,iBAAiB,CAAkC,KAAsB,EAAE,KAAyB,EAAE,KAAyB;IAC7I,MAAM,IAAI,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IACrC,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY;QAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IAC5E,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU;QAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IAC1E,IAAI,KAAK,KAAK,UAAU;QAAE,OAAO,IAAI,CAAC;IACtC,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU;QAAE,OAAO,KAAK,CAAC,OAAO,IAAI,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IACvH,MAAM,OAAO,GAAG,GAA4B,EAAE;QAC5C,IAAI,KAAK,CAAC,OAAO;YAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;QAC1D,IAAI,KAAK,CAAC,gBAAgB;YAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;QACtE,MAAM,MAAM,GAAG,yBAAyB,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QACvE,OAAO,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IACjF,CAAC,CAAC;IACF,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO;QAAE,OAAO,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;IACxI,IAAI,KAAK,KAAK,UAAU;QAAE,OAAO,IAAI,CAAC;IACtC,IAAI,KAAK,KAAK,MAAM;QAAE,OAAO,OAAO,EAAE,CAAC;IACvC,sGAAsG;IACtG,OAAO,IAAI,CAAC;AACd,CAAC;AAED,qGAAqG;AACrG,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,4FAA4F;IAC5F,iGAAiG;IACjG,WAAW,EAAE;QACX,kBAAkB,EAAE,CAAC;QACrB,QAAQ,EAAE,EAAE;QACZ,aAAa,EAAE,EAAE;QACjB,aAAa,EAAE,IAAI;QACnB,SAAS,EAAE,GAAG;QACd,cAAc,EAAE,GAAG;QACnB,YAAY,EAAE,CAAC;KAChB;IACD,QAAQ,EAAE,MAAM,CAAC,eAAe;IAChC,OAAO,EAAE,OAAO,CAAC,EAAE;IACnB,UAAU,EAAE,OAAO,CAAC,EAAE;IACtB,OAAO,EAAE,OAAO,CAAC,EAAE;IACnB,QAAQ,EAAE,OAAO,CAAC,EAAE;IACpB,oIAAoI;IACpI,cAAc,EAAE,MAAM,CAAC,eAAe,GAAG,CAAC;IAC1C,4FAA4F;IAC5F,eAAe,EAAE,KAAK;IACtB,wFAAwF;IACxF,cAAc,EAAE,EAAE;IAClB,oBAAoB,EAAE,EAAE;IACxB,cAAc,EAAE,GAAG;IACnB,qBAAqB,EAAE,EAAE;IACzB,iBAAiB,EAAE,GAAG;IACtB,kBAAkB,EAAE,EAAE;IACtB,gBAAgB,EAAE,CAAC;IACnB,gBAAgB,EAAE,CAAC;IACnB;;;;;;;OAOG;IACH,gBAAgB,EAAE,EAAE,SAAS,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;IACrF;;;;;;OAMG;IACH,OAAO,EAAE,EAAE,IAAI,EAAE,aAAa,CAAC,KAAK,CAAC,KAAK,EAAE,UAAU,EAAE,cAAc,CAAC,OAAO,CAAC,OAAO,EAAE,eAAe,EAAE,OAAO,CAAC,EAAE,EAAE;CAC7G,CAAC;AAGX,MAAM,UAAU,gCAAgC,CAAC,SAAiC,KAAK;IACrF,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,CAAC;QAC3E,MAAM,IAAI,SAAS,CAAC,8CAA8C,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACtF,CAAC;IACD,OAAO,mBAAmB,CAAC,gBAAgB,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;AAChE,CAAC;AAYD,MAAM,CAAC,MAAM,kBAAkB,GAAG,EAAE,KAAK,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,SAAS,EAGtF,CAAC;AACF,MAAM,eAAe,GAA8B,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;AAEtF,sFAAsF;AACtF,MAAM,UAAU,uBAAuB,CACrC,KAAgC,EAChC,MAAyD;IAEzD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAkB,CAAC;IACvC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC;YAAE,MAAM,IAAI,SAAS,CAAC,gCAAgC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACzG,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,MAAM,IAAI,SAAS,CAAC,8BAA8B,IAAI,EAAE,CAAC,CAAC;QAC9E,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACjB,CAAC;IACD,MAAM,OAAO,GAAG,EAAE,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;IACzD,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC;QACxB,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC;YAAE,MAAM,IAAI,UAAU,CAAC,cAAc,IAAI,6BAA6B,CAAC,CAAC;QAChH,OAAO,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;IACxB,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAoBD,4FAA4F;AAC5F,MAAM,UAAU,sBAAsB,CAAC,KAA6F,EAAE,OAA2B,SAAS;IACxK,OAAO,IAAI,KAAK,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,IAAI,CAAC,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,OAAO,KAAK,GAAG,CAAC;AACpH,CAAC;AACD,MAAM,UAAU,gBAAgB,CAAC,EAAE,KAAK,EAAE,QAAQ,GAAG,KAAK,EAAE,OAAO,GAAG,KAAK,EAAE,eAAe,GAAG,CAAC,EAA6B;IAC3H,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,eAAe,CAAC,IAAI,eAAe,GAAG,CAAC;QAAE,MAAM,IAAI,UAAU,CAAC,gDAAgD,CAAC,CAAC;IAC1I,OAAO,CAAC,QAAQ,IAAI,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,IAAI,eAAe,GAAG,CAAC,CAAC,CAAC;AACnF,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,iHAAiH;IACjH,uHAAuH;IACvH,UAAU,EAAE,YAAY,CAAC,KAAK,CAAC,KAAK;IACpC,SAAS,EAAE,OAAO,CAAC,EAAE;IACrB,SAAS,EAAE,OAAO,CAAC,GAAG;IACtB,OAAO,EAAE,OAAO,CAAC,GAAG;IACpB,YAAY,EAAE,EAAE;IAChB,mBAAmB,EAAE,EAAE;IACvB,kBAAkB,EAAE,CAAC;IACrB,sGAAsG;IACtG,cAAc,EAAE,CAAC;IACjB,UAAU,EAAE,OAAO,CAAC,EAAE;IACtB,mBAAmB,EAAE,IAAI;IACzB,8FAA8F;IAC9F,MAAM,EAAE,CAAC;IACT,QAAQ,EAAE,OAAO,CAAC,EAAE;IACpB,8GAA8G;IAC9G,wGAAwG;IACxG,SAAS,EAAE,CAAC;IACZ,UAAU,EAAE,EAAE;IACd,gBAAgB,EAAE,CAAC;IACnB,eAAe,EAAE,OAAO,CAAC,EAAE;IAC3B,qFAAqF;IACrF,aAAa,EAAE,EAAE;IACjB,6FAA6F;IAC7F,UAAU,EAAE,GAAG;IACf,QAAQ,EAAE,CAAC;IACX;;;OAGG;IACH,eAAe,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC,GAAG,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE;CACrG,CAAC;AAaX;;;;GAIG;AACH,MAAM,UAAU,0BAA0B,CAAC,EAAE,KAAK,EAAE,KAAK,EAAuB;IAC9E,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE;QAAE,MAAM,IAAI,SAAS,CAAC,6CAA6C,CAAC,CAAC;IACtF,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAC;IAC9B,OAAO,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;QACtB,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAAE,MAAM,IAAI,SAAS,CAAC,mDAAmD,CAAC,CAAC;QAClH,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE;YAAE,MAAM,IAAI,SAAS,CAAC,yCAAyC,CAAC,CAAC;QACvF,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,KAAK,GAAG,CAAC;YAAE,MAAM,IAAI,UAAU,CAAC,mDAAmD,CAAC,CAAC;QACnI,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACjB,OAAO,EAAE,GAAG,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,KAAK,IAAI,iBAAiB,CAAC,eAAe,CAAC,QAAQ,EAAE,CAAC;IAC1F,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,OAAO,EAAE,CAAC;IACV,MAAM,EAAE,OAAO,CAAC,GAAG;IACnB,uFAAuF;IACvF,OAAO,EAAE,IAAI;IACb,SAAS,EAAE,GAAG;IACd,WAAW,EAAE,IAAI;CACT,CAAC;AAEX;;;GAGG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,UAAU,EAAE,OAAO,CAAC,EAAE;IACtB,aAAa,EAAE,OAAO,CAAC,GAAG;IAC1B,WAAW,EAAE,SAAS;IACtB,IAAI,EAAE,OAAO;CACL,CAAC;AAEX,yGAAyG;AACzG,MAAM,UAAU,uBAAuB,CAAC,KAAa;IACnD,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC;QAAE,MAAM,IAAI,UAAU,CAAC,uCAAuC,CAAC,CAAC;IAC7G,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9D,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,wEAAwE;IACxE,kBAAkB,EAAE,CAAC;IACrB,wDAAwD;IACxD,UAAU,EAAE,OAAO,CAAC,GAAG;IACvB,oGAAoG;IACpG,WAAW,EAAE,OAAO;IACpB,gBAAgB,EAAE,KAAK,CAAC,EAAE;IAC1B;;;;OAIG;IACH,UAAU,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE;CAChH,CAAC;AAGX,qGAAqG;AACrG,MAAM,UAAU,4BAA4B,CAAC,IAA8B,EAAE,KAAa;IACxF,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,OAAO;QAAE,MAAM,IAAI,SAAS,CAAC,kDAAkD,CAAC,CAAC;IACpH,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE;QAAE,MAAM,IAAI,SAAS,CAAC,oDAAoD,CAAC,CAAC;AAC/F,CAAC;AAED,oGAAoG;AACpG,MAAM,UAAU,kBAAkB,CAAC,KAAa,EAAE,KAAa;IAC7D,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC;QAAE,MAAM,IAAI,UAAU,CAAC,wCAAwC,CAAC,CAAC;IAC9G,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,IAAI,KAAK;QAAE,MAAM,IAAI,UAAU,CAAC,kDAAkD,CAAC,CAAC;AAC5I,CAAC;AAED,iHAAiH;AACjH,MAAM,UAAU,sBAAsB,CAAC,QAAiB,EAAE,QAAiB;IACzE,IAAI,QAAQ,IAAI,QAAQ;QAAE,MAAM,IAAI,SAAS,CAAC,2CAA2C,CAAC,CAAC;AAC7F,CAAC;AAED,6GAA6G;AAC7G,MAAM,UAAU,sBAAsB,CAAC,KAAa,EAAE,KAAa;IACjE,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC;QAAE,MAAM,IAAI,UAAU,CAAC,wCAAwC,CAAC,CAAC;IAC9G,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;AAC7D,CAAC;AAED;;;;GAIG;AACH,4GAA4G;AAC5G,MAAM,CAAC,MAAM,yBAAyB,GAAG,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,EAAW,CAAC;AAEnG,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,KAAK,EAAE,EAAE;IACT,GAAG,EAAE,OAAO,CAAC,EAAE;IACf,WAAW,EAAE,EAAE;IACf,aAAa,EAAE,EAAE;IACjB,SAAS,EAAE,EAAE;IACb,WAAW,EAAE,GAAG;IAChB,eAAe,EAAE,EAAE;IACnB,YAAY,EAAE,EAAE;IAChB,QAAQ,EAAE,EAAE;CACJ,CAAC;AAKX;;;;GAIG;AACH,MAAM,UAAU,wBAAwB,CAAC,KAA+E;IACtH,MAAM,SAAS,GAAG,IAAI,GAAG,EAAoC,CAAC;IAC9D,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QAC5B,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAAE,MAAM,IAAI,SAAS,CAAC,4CAA4C,CAAC,CAAC;QACjH,MAAM,IAAI,GAAG,CAAC,KAAyC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI,CAAC,QAAQ,IAAI,KAAK,CAAC,SAAS,KAAK,IAAI,CAAC,SAAS,CAAC;QAC9I,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC;QACtE,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IAC5F,CAAC,CAAC,CAAC;IACH,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,yGAAyG;AACzG,MAAM,UAAU,8BAA8B,CAAC,WAAqC,QAAQ;IAC1F,IAAI,CAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAAE,MAAM,IAAI,SAAS,CAAC,qCAAqC,CAAC,CAAC;IAC1H,MAAM,MAAM,GAAG,QAAQ,KAAK,QAAQ,IAAI,QAAQ,KAAK,OAAO,CAAC;IAC7D,MAAM,IAAI,GAAG,QAAQ,KAAK,QAAQ,IAAI,QAAQ,KAAK,MAAM,CAAC;IAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC,CAAC,iBAAiB,CAAC,MAAM,EAAW,CAAC;AACnL,CAAC;AAkBD,MAAM,UAAU,uBAAuB,CAAC,MAA6B;IACnE,QAAO,MAAM,EAAC,CAAC;QAAA,KAAK,QAAQ,CAAC,CAAA,OAAO,SAAS,CAAC;QAAA,KAAK,QAAQ,CAAC,CAAA,OAAO,UAAU,CAAC;QAAA,KAAK,SAAS,CAAC,CAAA,OAAO,UAAU,CAAC;QAAA,KAAK,aAAa,CAAC,CAAA,OAAO,IAAI,CAAC;QAAA,OAAO,CAAC,CAAA,MAAM,IAAI,SAAS,CAAC,0BAA0B,CAAC,CAAC;IAAA,CAAC;AACzM,CAAC;AAKD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,uBAAuB,CACrC,MAA8B,EAC9B,QAA6E;IAE7E,MAAM,MAAM,GAAyE,EAAE,CAAC;IACxF,IAAI,uBAAuB,CAAC,MAAM,CAAC,KAAK,IAAI;QAAE,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC;IACpG,IAAI,QAAQ,CAAC,OAAO,IAAI,MAAM,KAAK,QAAQ;QAAE,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC,CAAC;IACrG,IAAI,QAAQ,CAAC,WAAW,IAAI,MAAM,KAAK,SAAS;QAAE,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC,CAAC;IAC9G,IAAI,QAAQ,CAAC,IAAI;QAAE,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;IACpE,OAAO,MAAM,CAAC;AAChB,CAAC;AACD,MAAM,UAAU,qBAAqB,CAAC,KAAY,EAAC,KAAY;IAC9D,IAAG,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAE,KAAK,GAAC,CAAC,IAAE,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAE,KAAK,GAAC,CAAC,IAAE,KAAK,IAAE,KAAK;QAAC,MAAM,IAAI,UAAU,CAAC,wCAAwC,CAAC,CAAC;IACrJ,OAAO,EAAC,KAAK,EAAC,KAAK,KAAG,CAAC,EAAC,IAAI,EAAC,KAAK,KAAG,KAAK,GAAC,CAAC,EAAC,CAAC;AAC/C,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,UAAU,EAAE,EAAE;IACd,eAAe,EAAE,EAAE;IACnB,SAAS,EAAE,OAAO,CAAC,EAAE;IACrB,qGAAqG;IACrG,OAAO,EAAE,OAAO,CAAC,GAAG;IACpB,MAAM,EAAE,OAAO,CAAC,EAAE;IAClB,qFAAqF;IACrF,WAAW,EAAE,EAAE,GAAG,OAAO,CAAC,EAAE;IAC5B,kGAAkG;IAClG,eAAe,EAAE,EAAE;IACnB,0FAA0F;IAC1F,aAAa,EAAE,GAAG;IAClB,WAAW,EAAE,MAAM,CAAC,EAAE;IACtB,sHAAsH;IACtH,kGAAkG;IAClG,QAAQ,EAAE,OAAO,CAAC,EAAE;IACpB,6FAA6F;IAC7F,aAAa,EAAE,KAAK,CAAC,EAAE;IACvB;;;;;;OAMG;IACH,YAAY,EAAE,EAAE,iBAAiB,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,EAAE;CACjE,CAAC;AAOX,8HAA8H;AAC9H,MAAM,UAAU,uBAAuB,CAAqB,KAAgD;IAC1G,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAC;IAC9B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE;YAAE,MAAM,IAAI,SAAS,CAAC,4DAA4D,CAAC,CAAC;QACjJ,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACnB,CAAC;IACD,OAAO,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC;AAC5G,CAAC;AAED,qGAAqG;AACrG,MAAM,UAAU,qBAAqB,CAAC,KAAiD;IACtF,MAAM,KAAK,GAAC,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAA,EAAE,CAAA,IAAI,CAAC,QAAQ,KAAG,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAA,EAAE,CAAA,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IAAA,MAAM,GAAG,GAAC,IAAI,GAAG,EAAU,CAAC;IAC7G,KAAI,MAAM,IAAI,IAAI,KAAK,EAAC,CAAC;QAAA,IAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,IAAE,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAAC,MAAM,IAAI,SAAS,CAAC,yCAAyC,CAAC,CAAC;QAAA,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAAA,IAAG,IAAI,CAAC,QAAQ,KAAG,IAAI,IAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAE,IAAI,CAAC,QAAQ,KAAG,IAAI,CAAC,EAAE,CAAC;YAAC,MAAM,IAAI,SAAS,CAAC,0CAA0C,CAAC,CAAC;IAAA,CAAC;AAC9R,CAAC;AAID,MAAM,UAAU,0BAA0B,CAAC,WAAmD;IAC5F,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAC;IAC9B,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;QAC/B,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE;YAAE,MAAM,IAAI,SAAS,CAAC,6DAA6D,CAAC,CAAC;QACxJ,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACnB,CAAC;AACH,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,YAAY,CAAC,EAAU,EAAE,EAAU;IACjD,OAAO,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,mBAAmB,CAAC,kBAAkB,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;AACnG,CAAC;AAUD,oGAAoG;AACpG,MAAM,UAAU,iBAAiB,CAAsB,KAAkB,EAAC,WAAsC,EAAC,YAAkC,EAAC,cAAoC;IACtL,MAAM,GAAG,GAAC,IAAI,GAAG,EAAU,EAAC,MAAM,GAAC,IAAI,GAAG,EAAU,CAAC;IACrD,KAAI,MAAM,IAAI,IAAI,KAAK,EAAC,CAAC;QAAA,IAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,IAAE,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE;YAAC,MAAM,IAAI,SAAS,CAAC,oDAAoD,CAAC,CAAC;QAAA,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAAA,CAAC;IAC9K,KAAI,MAAM,KAAK,IAAI,WAAW,EAAC,CAAC;QAAA,IAAG,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,IAAE,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,IAAE,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE;YAAC,MAAM,IAAI,SAAS,CAAC,0DAA0D,CAAC,CAAC;QAAA,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAAA,CAAC;IACrM,MAAM,UAAU,GAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAA,EAAE,CAAA,IAAI,CAAC,EAAE,KAAG,YAAY,CAAC,CAAC;IAChE,+FAA+F;IAC/F,MAAM,IAAI,GAAC,YAAY,KAAG,SAAS,IAAE,CAAC,YAAY,KAAG,IAAI,IAAE,CAAC,UAAU,CAAC,CAAC;IACxE,MAAM,OAAO,GAAC,IAAI,IAAE,YAAY,KAAG,IAAI,CAAA,CAAC,CAAA,KAAK,CAAA,CAAC,CAAA,KAAK,CAAC,MAAM,CAAC,IAAI,CAAA,EAAE,CAAA,UAAU,EAAE,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IACxG,OAAO,EAAC,IAAI,EAAC,UAAU,EAAC,OAAO,EAAC,QAAQ,EAAC,IAAI,CAAA,CAAC,CAAA,SAAS,CAAA,CAAC,CAAA,OAAO,CAAC,IAAI,CAAC,IAAI,CAAA,EAAE,CAAA,IAAI,CAAC,EAAE,KAAG,cAAc,CAAC,EAAC,CAAC;AACxG,CAAC;AAUD,MAAM,UAAU,wBAAwB,CAAC,KAAa,EAAE,cAAuB;IAC7E,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC3B,IAAI,CAAC,KAAK;QAAE,OAAO,MAAM,CAAC;IAC1B,IAAI,cAAc,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IACnD,OAAO,KAAK,KAAK,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC;AAChE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAAa;IAC/C,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC1B,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AAC5B,CAAC;AASD,MAAM,UAAU,uBAAuB,CAAC,KAAoB,EAAE,kBAA0B;IACtF,0FAA0F;IAC1F,IAAI,CAAC,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,kBAAkB,CAAC,IAAI,kBAAkB,GAAG,CAAC,EAAE,CAAC;QAC3I,MAAM,IAAI,UAAU,CAAC,4CAA4C,CAAC,CAAC;IACrE,CAAC;IACD,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,GAAG,CAAC;QAAE,OAAO,MAAM,CAAC;IAC/C,OAAO,kBAAkB,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC;AACtD,CAAC;AASD,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAiD,CAAC;AACtG;;;;;GAKG;AACH,MAAM,UAAU,8BAA8B,CAAC,KAAwB,EAAE,OAAgB,EAAE,KAAuB,EAAE,OAA0B,QAAQ;IACpJ,IAAI,CAAC,kBAAkB,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,UAAU,CAAC,kDAAkD,CAAC,CAAC;IACjH,IAAI,OAAO,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACjD,OAAO,KAAK,KAAK,OAAO,IAAI,IAAI,KAAK,OAAO,CAAC;AAC/C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,wBAAwB,CAAC,YAAoB,EAAE,SAAiB;IAC9E,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,YAAY,CAAC,IAAI,YAAY,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;QACzG,MAAM,IAAI,UAAU,CAAC,8CAA8C,CAAC,CAAC;IACvE,CAAC;IACD,OAAO,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,SAAS,GAAG,CAAC,CAAC,CAAC;AACtE,CAAC;AAED,2FAA2F;AAC3F,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,8EAA8E;IAC9E,UAAU,EAAE,GAAG;IACf,8GAA8G;IAC9G,aAAa,EAAE,CAAC;IAChB,kDAAkD;IAClD,iBAAiB,EAAE,CAAC;IACpB,2DAA2D;IAC3D,WAAW,EAAE,CAAC;IACd,iDAAiD;IACjD,UAAU,EAAE,OAAO,CAAC,EAAE;IACtB,wEAAwE;IACxE,SAAS,EAAE,OAAO,CAAC,EAAE;IACrB,8DAA8D;IAC9D,OAAO,EAAE,OAAO,CAAC,EAAE;CACX,CAAC;AAEX,8FAA8F;AAC9F,MAAM,UAAU,uBAAuB,CAAC,QAAgB,kBAAkB,CAAC,UAAU;IACnF,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,MAAM,IAAI,UAAU,CAAC,kCAAkC,CAAC,CAAC;IACtF,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;AAC5B,CAAC;AAED,oGAAoG;AACpG,MAAM,UAAU,qBAAqB,CAAC,EAAU,EAAE,EAAU;IAC1D,iGAAiG;IACjG,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACjE,CAAC;AAED;oFACoF;AACpF,MAAM,uBAAuB,GAAG;IAC9B,GAAG,EAAE,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE,eAAe,EAAE,EAAE;IAC3D,aAAa,EAAE,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,YAAY,EAAE,EAAE,EAAE,aAAa,EAAE,EAAE;CAC9E,CAAC;AACX,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,GAAG,uBAAuB;IAC1B,oGAAoG;IACpG,mBAAmB,EAAE,uBAAuB,CAAC,aAAa,GAAG,uBAAuB,CAAC,UAAU,GAAG,uBAAuB,CAAC,GAAG;IAC7H,WAAW,EAAE,EAAE,eAAe,EAAE,OAAO,CAAC,QAAQ,EAAE,cAAc,EAAE,OAAO,CAAC,OAAO,EAAE;CAC3E,CAAC;AAEX,yEAAyE;AACzE,MAAM,CAAC,MAAM,oBAAoB,GAAG,MAAM,CAAC,MAAM,CAAC;IAChD,UAAU,EAAE,EAAE;IACd,eAAe,EAAE,KAAK,CAAC,GAAG;IAC1B,cAAc,EAAE,MAAM,CAAC,MAAM,CAAC;QAC5B,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,IAAI,EAAW,CAAC;QAC7D,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,IAAI,EAAW,CAAC;KAC9D,CAAC;IACF;;;;OAIG;IACH,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,OAAO,EAAW,CAAC;CACzE,CAAC,CAAC;AAYH,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,aAAa,EAAE,EAAE,EAAE,sBAAsB,EAAE,EAAE,EAAE,uBAAuB,EAAE,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,EAAE,UAAU,EAAE,KAAK;IACnL,uFAAuF;IACvF,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,CAA4C;IAC5G,6FAA6F;IAC7F,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,aAAa,EAAE,OAAO,CAAC,cAAc,EAAE,cAAc,EAAE,OAAO,CAAC,OAAO,EAAE,eAAe,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC;IACxI,WAAW,EAAE,EAAE,EAAE,WAAW,EAAE,EAAE;IAChC;;;;;OAKG;IACH,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC;IACpD,6GAA6G;IAC7G,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;IACjD,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,SAA0B,EAAE,KAAK,EAAE,UAA2B,EAAE,IAAI,EAAE,OAAuB,EAAE,kBAAkB,EAAE,SAAqC,EAAE,CAAC,EAAE,CAAC,CAAC;AASlM,wHAAwH;AACxH,MAAM,UAAU,uBAAuB,CAAC,SAAiB;IACvD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,SAAS,GAAG,CAAC;QAAE,MAAM,IAAI,UAAU,CAAC,0DAA0D,CAAC,CAAC;IACnI,OAAO,IAAI,CAAC,GAAG,CAAC,cAAc,CAAC,WAAW,EAAE,IAAI,CAAC,GAAG,CAAC,cAAc,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC,CAAC;AAC/F,CAAC","sourcesContent":["import { control, glyph, layout, opacity, radius, spacing } from \"./foundations.js\";\nimport { avatarRecipe, emptyStateRecipe, spinnerRecipe, type CornerAccessoryPlacement } from \"./component-recipes.js\";\nimport { semanticColors } from \"./semantic-colors.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 // 2026-10-18: empty copy stays at the 14pt body size, including full-screen compositions.\n titleVariant: state.kind === \"empty\" ? emptyStateRecipe.title.textVariant : \"title\",\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 * `body-bleed`: header, notice and footer keep the shell padding; the body has no gutter on any side, so a map or\n * canvas meets the header (or notice), the screen edges and the footer. With no footer the body is still the last\n * region and clears the bottom insets the screen owns (`safeAreaBottom`, an overlay BottomNavigation) without the\n * gutter. choose-window's map screens used `body-edge` and kept a 16pt strip above and below the map (2026-10-18).\n */\nexport type ScreenContentInset = \"default\" | \"none\" | \"body-edge\" | \"body-bleed\";\nexport const screenContentInsets = [\"default\", \"none\", \"body-edge\", \"body-bleed\"] as const satisfies readonly ScreenContentInset[];\n\n/**\n * 2026-10-18 사용자 지시: 입력 자동 포커스는 페이지 진입에만 적용하고 하단 시트에서는 폐지한다.\n * 페이지는 `first-input`으로 명시한 주 입력 또는 첫 유효 입력을 한 번 고른다. 하단 시트는 renderer의\n * 상속 경계에서 중첩 화면까지 자동 포커스를 막는다. Dialog·측면 시트의 모달 포커스 계약은 유지한다.\n * `single-input`은 Dialog·측면 시트의 단일 입력 선택, `none`은 입력 자동 선택을 끈다.\n * 비활성·읽기 전용·initialFocusTarget={false} 칸은 제외한다. 이미 포커스된 입력을 빼앗지 않으며\n * 화면은 mount당 한 번만 포커스한다. 모션 감소는 포커스 정책을 바꾸지 않는다.\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 // 2026-10-18: input focus belongs to page entry, including chat/auth pages; bottom sheets opt out at their boundary.\n screen: \"first-input\",\n search: \"first-input\",\n editor: \"first-input\",\n chat: \"first-input\",\n commentThread: \"first-input\",\n overlay: \"single-input\",\n auth: \"first-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/**\n * 진입 포커스 창(2026-10-18 1.28.1 앱 채택 점검). mount 시점 한 번만 고르면 세 경우가 앱 우회로 남았다: 진입 때 열린\n * 모달 아래 칸(번뚝 첫 가입 약관), 진입 중 비동기로 나타나는 칸(번뚝 계정 삭제 확인), 사용자 행동으로 나중에 나타나는 칸\n * (utilverse 검색 열기, 번뚝 아이디어 시트·spint 작성 단계). 그래서 범위는 아래 상태를 가진다.\n *\n * - `entering`: 진입 중(Native 전환·시트 등장 interaction 전). 칸 등록만 받는다.\n * - `open`: 진입이 끝났지만 아직 포커스하지 못했다. 칸이 새로 등록되거나 위 오버레이가 닫히면 다시 고른다. 모달 아래에서\n * 진입한 화면은 모달이 닫힐 때 사용자가 그 화면을 아직 만지지 않았으면 그때 포커스한다.\n * - `settled`: 포커스했거나, 사용자가 범위를 직접 조작(터치·포인터·키·휠)했거나, 이미 다른 텍스트 칸에 초점이 있다.\n * 이후에 입력이 새로 나타나도 자동 포커스를 다시 시작하지 않는다(2026-10-18 페이지 진입에만 적용).\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 // Page entry only: revealing a marked field after interaction/entry must not open the keyboard again.\n return 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 // Full-screen reading routes use fixed travel, unlike a Sheet's fraction of its own height.\n // Migrated from Diairy's handle/top-bounce contract so products no longer own dismissal physics.\n pullDismiss: {\n activationDistance: 6,\n distance: 80,\n flickDistance: 32,\n flickVelocity: 0.65,\n maxOffset: 160,\n settleDuration: 140,\n topTolerance: 1,\n },\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 /**\n * In-place room CompositionLayout's loading/empty/error/restricted replacement keeps (`stateHeight`), so the state\n * centers inside a section that has no parent height. 2026-10-23 audit: Yajalal wrapped 13+ layouts in\n * `<View style={{ minHeight: N }}>` + `layoutStyle={{ flex: 1 }}` with 36–220. The steps follow those values:\n * `compact` 96 (rails, inline save errors, share-card rows: 68–96), `regular` 160 (a list/table section's body:\n * 120–180), `large` 220 (a field or chart panel). `fit` keeps the state's own height (an inline loading line).\n * Ready content is never stretched by this floor.\n */\n compositionState: { minHeight: { fit: null, compact: 96, regular: 160, large: 220 } },\n /**\n * Pull to refresh (Native ScreenLayout `onRefresh`). Without a product `loadingIndicator` the system control spins in\n * the shared brand spinner tone on the surface plate. With one, the system control stays for the gesture but is\n * drawn transparent and the product visual sits `indicatorOffset` below the body top, centered, while `refreshing`.\n * 2026-10-23: spint Home, Notifications and Cell each set `tintColor=\"transparent\"` and put FlowerSpinner in a list\n * header by hand.\n */\n refresh: { tint: spinnerRecipe.tones.brand, background: semanticColors.surface.default, indicatorOffset: spacing.md },\n} as const;\n\nexport type CompositionStateHeight = keyof typeof screenPatternRecipe.compositionState.minHeight;\nexport function resolveCompositionStateMinHeight(height: CompositionStateHeight = \"fit\"): number | null {\n if (!Object.hasOwn(screenPatternRecipe.compositionState.minHeight, height)) {\n throw new TypeError(`Unsupported CompositionLayout stateHeight: ${String(height)}`);\n }\n return screenPatternRecipe.compositionState.minHeight[height];\n}\n\n/**\n * Native host outside the screens: window safe-area insets and the canvas behind them. 2026-10-23 audit: choose-window\n * (`app/_layout.tsx` AppCanvas), Unairplane (`ui/index.tsx` AppScreenHost, FlightLookupScreen, BoardingPassScanner)\n * each wrapped routes in `SafeAreaView edges={[\"top\",\"left\",\"right\"]}` painted `colors.bg`, because ScreenLayout only\n * took top/bottom numbers and its root stops at the reading width, so the window background showed in the notch and\n * beside the column. The bottom stays out of the default: ScreenLayout `safeAreaBottom` pads the last region\n * max(gutter, inset) once, and a host bottom inset would add the gutter on top of it.\n */\nexport type ScreenHostEdge = \"top\" | \"right\" | \"bottom\" | \"left\";\nexport type ScreenHostSurface = \"default\" | \"transparent\";\nexport const screenHostDefaults = { edges: [\"top\", \"right\", \"left\"], surface: \"default\" } as const satisfies {\n edges: readonly ScreenHostEdge[];\n surface: ScreenHostSurface;\n};\nconst screenHostEdges: readonly ScreenHostEdge[] = [\"top\", \"right\", \"bottom\", \"left\"];\n\n/** Padding a ScreenHost applies from window insets; edges outside the list stay 0. */\nexport function resolveScreenHostInsets(\n edges: readonly ScreenHostEdge[],\n insets: Readonly<Partial<Record<ScreenHostEdge, number>>>,\n): Readonly<Record<ScreenHostEdge, number>> {\n const seen = new Set<ScreenHostEdge>();\n for (const edge of edges) {\n if (!screenHostEdges.includes(edge)) throw new TypeError(`Unsupported ScreenHost edge: ${String(edge)}`);\n if (seen.has(edge)) throw new TypeError(`Duplicate ScreenHost edge: ${edge}`);\n seen.add(edge);\n }\n const padding = { top: 0, right: 0, bottom: 0, left: 0 };\n for (const edge of seen) {\n const value = insets[edge] ?? 0;\n if (!Number.isFinite(value) || value < 0) throw new RangeError(`ScreenHost ${edge} inset must be non-negative`);\n padding[edge] = value;\n }\n return padding;\n}\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 /** Counters can align to the field end; validation errors retain their normal alignment. */\n descriptionAlign?: \"start\" | \"end\";\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 // 2026-10-23: Telegram-style quote rail remains visible inside both neutral and filled brand bubbles.\n quoteRailWidth: 3,\n quoteInset: spacing.xs,\n quoteSurfaceOpacity: 0.12,\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 // The supplied reference keeps the tip on the top edge and curves its underside into the bubble (2026-10-20).\n // Add tailCornerRadius to the drawn width so the tail overlaps the rounded bubble corner without a gap.\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 /**\n * Reaction summary pill beside the time (2026-10-18 BurnTok DM): one button that opens the same hold menu.\n * Counts below `minCount` show the emoji alone, as the measured DM references do for a single reaction.\n */\n reactionSummary: { minHeight: 24, paddingInline: spacing.xs, itemGap: spacing.xxs, emojiGap: 2, minCount: 2 },\n} as const;\n\nexport type ChatReactionSummaryItem = Readonly<{ id: string; emoji: string; count: number }>;\nexport type ChatReactionSummary = Readonly<{\n label: string;\n items: readonly ChatReactionSummaryItem[];\n /**\n * Counts only, for readers who cannot react (2026-10-18 Utilverse guests): drawn in the same place beside the time\n * as non-interactive text named by `label`, without the pill surface, so it does not look or act like a control.\n * Default `false` (the pill button that opens the hold menu).\n */\n readOnly?: boolean;\n}>;\n/**\n * Validates ChatMessage `reactions.summary` and marks which counts are drawn. The label (the button's accessible name)\n * is required; ids are unique and non-empty, emoji non-empty and counts positive integers; a count below\n * `reactionSummary.minCount` shows the emoji alone.\n */\nexport function resolveChatReactionSummary({ label, items }: ChatReactionSummary): readonly (ChatReactionSummaryItem & Readonly<{ showCount: boolean }>)[] {\n if (!label.trim()) throw new TypeError(\"Reaction summary requires a localized label\");\n const ids = new Set<string>();\n return items.map(item => {\n if (!item.id.trim() || ids.has(item.id)) throw new TypeError(\"Reaction summary ids must be unique and non-empty\");\n if (!item.emoji.trim()) throw new TypeError(\"Reaction summary items require an emoji\");\n if (!Number.isSafeInteger(item.count) || item.count < 1) throw new RangeError(\"Reaction summary counts must be positive integers\");\n ids.add(item.id);\n return { ...item, showCount: item.count >= chatMessageRecipe.reactionSummary.minCount };\n });\n}\n\n/**\n * \"Someone is typing\" row in a chat timeline (2026-10-18 BurnTok DM). It reuses the incoming bubble geometry\n * (chatMessageRecipe) so it reads as the next incoming message; only the dots are its own values. Under reduced\n * motion the dots stay at full opacity instead of pulsing.\n */\nexport const typingIndicatorRecipe = {\n dotSize: 6,\n dotGap: spacing.xxs,\n /** One pulse of the three dots; each dot starts `staggerMs` after the previous one. */\n cycleMs: 1200,\n staggerMs: 160,\n restOpacity: 0.35,\n} as const;\n\n/**\n * Centered date (or time) row between timeline groups (2026-10-18 Utilverse chat, which drew it as a product\n * caption). The next message still owns its own group gap above it, so this row only adds the space before it.\n */\nexport const chatDateSeparatorRecipe = {\n paddingTop: spacing.sm,\n paddingBottom: spacing.xxs,\n textVariant: \"caption\",\n tone: \"muted\",\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 * Paged photo album for ChatMessage `mediaAlbum` and CommentThreadItem `mediaAlbum` (2026-10-18, Utilverse social\n * photos). Only the shown page is rendered, so a product that authorizes each image can fetch one photo at a time\n * instead of every photo in a timeline row. The counter row matches CarouselMotion `navigation=\"counter\"`:\n * previous icon · position · next icon under the page; the frame keeps the host's media width and radius.\n */\nexport const mediaAlbumRecipe = {\n /** Page frame width / height when the product gives no aspect ratio. */\n defaultAspectRatio: 1,\n /** Space between the page frame and the counter row. */\n controlGap: spacing.xxs,\n /** Previous/next are small ghost IconButtons so the counter row stays compact beside thumbnails. */\n controlSize: \"small\",\n controlGlyphSize: glyph.sm,\n /**\n * Loading / failed page drawn by `MediaAlbumPageStatus` (2026-10-18 Utilverse: the page frame was one accessible\n * image, so the loading text and retry button inside it were unreachable by screen readers). The status block is\n * centered in the frame (VQ-09); retry is a small secondary Button.\n */\n pageStatus: { gap: spacing.xs, padding: spacing.sm, textVariant: \"caption\", retryTone: \"secondary\", retrySize: \"small\" },\n} as const;\n\nexport type MediaAlbumPageStatusKind = \"loading\" | \"error\";\n/** A page status names what the reader is waiting for or what failed; the label is the only copy. */\nexport function validateMediaAlbumPageStatus(kind: MediaAlbumPageStatusKind, label: string): void {\n if (kind !== \"loading\" && kind !== \"error\") throw new TypeError(\"Media album page status must be loading or error\");\n if (!label.trim()) throw new TypeError(\"Media album page status requires a localized label\");\n}\n\n/** A controlled index outside the set is a contract error, like Carousel's unknown `currentKey`. */\nexport function validateMediaAlbum(count: number, index: number): void {\n if (!Number.isSafeInteger(count) || count < 1) throw new RangeError(\"Media album requires at least one page\");\n if (!Number.isSafeInteger(index) || index < 0 || index >= count) throw new RangeError(\"Media album index must point at an existing page\");\n}\n\n/** One message or comment carries one photo set: either the eager `media` previews or the paged `mediaAlbum`. */\nexport function validateMediaSetChoice(hasMedia: boolean, hasAlbum: boolean): void {\n if (hasMedia && hasAlbum) throw new TypeError(\"Pass either media or mediaAlbum, not both\");\n}\n\n/** Uncontrolled albums keep the nearest page when the product's photo set shrinks (moderation, deletion). */\nexport function resolveMediaAlbumIndex(count: number, index: number): number {\n if (!Number.isSafeInteger(count) || count < 1) throw new RangeError(\"Media album requires at least one page\");\n return Math.min(Math.max(0, Math.trunc(index)), count - 1);\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}\n/** Footer slot of PermissionScreen in display order. */\nexport type PermissionFooterSlot = \"primary\" | \"recheck\" | \"alternative\" | \"skip\";\n/** Button emphasis per slot: one filled primary, framed same-width secondaries, a quiet skip last. */\nexport type PermissionFooterEmphasis = \"primary\" | \"secondary\" | \"ghost\";\n/**\n * Footer order and hierarchy (2026-10-23). Unairplane's boarding-pass scanner put \"check again\" and \"choose a photo\"\n * as Buttons inside `explanation` because the footer had only primary + skip, so their order, width and emphasis\n * differed from the footer. HJM now owns them:\n * 1. primary — request / settings / continue from `resolvePermissionAction`;\n * 2. recheck — re-read the OS permission after the user returns from settings; only while `denied`;\n * 3. alternative — a path that works without the permission (pick a photo, type it in); hidden once `granted`,\n * where the screen only continues;\n * 4. skip — leave the feature (ghost, last), unchanged.\n * Secondaries are framed and full width like the primary (SELECTION 보조 행동: 주 행동 아래 같은 폭 secondary).\n */\nexport function resolvePermissionFooter(\n status: PermissionScreenStatus,\n supplied: Readonly<{ recheck: boolean; alternative: boolean; skip: boolean }>,\n): readonly Readonly<{ slot: PermissionFooterSlot; emphasis: PermissionFooterEmphasis }>[] {\n const footer: { slot: PermissionFooterSlot; emphasis: PermissionFooterEmphasis }[] = [];\n if (resolvePermissionAction(status) !== null) footer.push({ slot: \"primary\", emphasis: \"primary\" });\n if (supplied.recheck && status === \"denied\") footer.push({ slot: \"recheck\", emphasis: \"secondary\" });\n if (supplied.alternative && status !== \"granted\") footer.push({ slot: \"alternative\", emphasis: \"secondary\" });\n if (supplied.skip) footer.push({ slot: \"skip\", emphasis: \"ghost\" });\n return footer;\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 // 2026-10-20 Spint feedback: separate comment blocks and identity/body/action lines for readability.\n lineGap: spacing.xxs,\n rowGap: spacing.lg,\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 // Inline per-comment panel (edit/report/block form) under the action row (2026-10-18, Utilverse): a form reads as its\n // own block, so it sits a full spacing step below the reply line instead of the compact line gap.\n panelGap: spacing.xs,\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 * What the SearchScreen filter rail does to a result. `narrow` (default) only removes results, so with nothing applied\n * a zero result is the query's and no filter can bring results back. `scope` chooses what is searched (keyword vs\n * address, region, map area): changing it can turn a zero into results even with nothing applied (2026-10-18:\n * choose-window's keyword/address switch is the recovery for a zero result, so it skipped resultSummary entirely).\n */\nexport type SearchFiltersRole = \"narrow\" | \"scope\";\nexport const searchFiltersRoles = [\"narrow\", \"scope\"] as const satisfies readonly SearchFiltersRole[];\n/**\n * Whether SearchScreen shows its filter rail (`filters` and the filter sheet trigger). Two-step search shows it only\n * beside results so typing keeps the pinned area short. A query-caused zero hides it only when the filters narrow,\n * because then none of them can fix the zero; scope filters stay as the recovery path. A filter-caused zero always keeps\n * it so the cause can be undone. Both renderers call this so the rule cannot drift between platforms.\n */\nexport function resolveSearchFilterRailVisible(phase: SearchScreenPhase, twoStep: boolean, cause: SearchEmptyCause, role: SearchFiltersRole = \"narrow\"): boolean {\n if (!searchFiltersRoles.includes(role)) throw new RangeError(\"SearchScreen filtersRole must be narrow or scope\");\n if (twoStep && phase !== \"results\") return false;\n return cause !== \"query\" || role === \"scope\";\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. */\nconst notificationRowGeometry = {\n gap: 12, contentGap: 4, avatarSize: 44, avatarBadgeSize: 20,\n thumbnailSize: 44, unreadSize: 6, previewLines: 2, paddingBlock: 12, paddingInline: 16,\n} as const;\nexport const notificationRowRecipe = {\n ...notificationRowGeometry,\n // Virtualized inboxes provide the section boundary; the shared row owns the text-aligned separator.\n separatorInsetStart: notificationRowGeometry.paddingInline + notificationRowGeometry.avatarSize + notificationRowGeometry.gap,\n interaction: { disabledOpacity: opacity.disabled, pressedOpacity: opacity.pressed },\n} as const;\n\n/** Shared profile identity geometry; product owns the avatar content. */\nexport const profileSummaryRecipe = Object.freeze({\n avatarSize: 72,\n avatarGlyphSize: glyph.xxl,\n actionsLayouts: Object.freeze({\n inline: Object.freeze({ axis: \"inline\", gap: \"xs\" } as const),\n stacked: Object.freeze({ axis: \"block\", gap: \"xs\" } as const),\n }),\n /**\n * ProfileScreen `editPlacement=\"summary\"` draws the edit action first in the summary's action row. A framed small\n * button reads as the card's own action; the below-summary placement keeps its ghost button (2026-10-15 utilverse\n * account decision: the edit action belongs inside the profile card).\n */\n editAction: Object.freeze({ tone: \"secondary\", size: \"small\" } as const),\n});\n\n/** Launcher artwork stays above its caption; product overlays may extend beyond the icon frame. */\n/**\n * Frame of an IconTile icon (2026-10-18 Utilverse launcher). `surface` draws the shared filled, hairlined frame;\n * `none` leaves product artwork that is already a complete launcher icon unframed. `shape` follows the product's\n * icon theme (squircle on iPhone shells, square on Windows/Linux shells); `size: \"fill\"` lets the icon span its\n * grid cell between `fillMinSize` and `fillMaxSize` instead of a product computing the cell size.\n */\nexport type IconTileFrame = \"surface\" | \"none\";\nexport type IconTileShape = \"squircle\" | \"square\" | \"circle\";\nexport type IconTileSize = \"fixed\" | \"fill\";\nexport const iconTileRecipe = Object.freeze({ iconSize: 64, labelMaxWidth: 72, multilineLabelMaxWidth: 84, multilineLabelMinHeight: 44, ghostOpacity: 0.55, gap: 6, iconRadius: \"22%\",\n /** Corner radius as a fraction of the icon size; `squircle` keeps the original 22%. */\n shapes: Object.freeze({ squircle: 0.22, square: 0, circle: 0.5 }) as Readonly<Record<IconTileShape, number>>,\n // Standalone tile activation must not add Button face padding around a narrow launcher cell.\n activation: Object.freeze({ minimumTarget: control.minTouchTarget, pressedOpacity: opacity.pressed, disabledOpacity: opacity.disabled }),\n fillMinSize: 48, fillMaxSize: 68,\n /**\n * `locked`: the tile stays pressable so the product can explain why (sign-in required), drawn at the disabled\n * opacity, and its name gains the product's `lockedLabel`. Utilverse ToolboxScreen dimmed an outer View with\n * activation.disabledOpacity and put the lock badge at `right: -4, top: -4` (2026-10-23); the corner accessory keeps\n * full opacity so the reason mark stays legible.\n */\n locked: Object.freeze({ opacity: opacity.disabled }),\n /** Corner mark on the icon frame; `offset` is the outward overhang (Asset/Avatar meaning), spacing.xxs 4. */\n accessory: Object.freeze({ offset: spacing.xxs }),\n defaults: Object.freeze({ frame: \"surface\" as IconTileFrame, shape: \"squircle\" as IconTileShape, size: \"fixed\" as IconTileSize, accessoryPlacement: \"top-end\" as CornerAccessoryPlacement }) });\n\n/**\n * What an IconTile passes to an `icon` render function: the rendered icon edge (`iconSize` for `fixed`, the measured\n * cell-clamped edge for `fill`). Fixed-size artwork (images, generated launcher art) sizes itself from it; Utilverse\n * re-computed the 48–68 clamp from its grid width to size its artwork (2026-10-18).\n */\nexport type IconTileArtwork = Readonly<{ edge: number }>;\n\n/** The edge a `size=\"fill\"` icon takes in a cell of `cellWidth`, for layout estimates made before the tile measures. */\nexport function resolveIconTileFillEdge(cellWidth: number): number {\n if (!Number.isFinite(cellWidth) || cellWidth < 0) throw new RangeError(\"IconTile cell width must be a non-negative finite number\");\n return Math.min(iconTileRecipe.fillMaxSize, Math.max(iconTileRecipe.fillMinSize, cellWidth));\n}\n"]}
package/dist/version.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  /** Package release shown by documentation surfaces. Kept in sync by a test. */
2
- export declare const designSystemVersion: "1.42.0";
2
+ export declare const designSystemVersion: "1.43.0";
3
3
  //# sourceMappingURL=version.d.ts.map
package/dist/version.js CHANGED
@@ -1,3 +1,3 @@
1
1
  /** Package release shown by documentation surfaces. Kept in sync by a test. */
2
- export const designSystemVersion = "1.42.0";
2
+ export const designSystemVersion = "1.43.0";
3
3
  //# sourceMappingURL=version.js.map
@@ -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.42.0\" as const;\n"]}
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.43.0\" as const;\n"]}
@@ -1,6 +1,6 @@
1
1
  # Component maturity and evidence manifest
2
2
 
3
- > Generated from `@hjmds/design-contracts` 1.42.0. Do not edit this file directly; run `pnpm contracts:sync`.
3
+ > Generated from `@hjmds/design-contracts` 1.43.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
 
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "designSystemVersion": "1.42.0",
3
+ "designSystemVersion": "1.43.0",
4
4
  "source": "packages/design-contracts/docs/generated/showcase-manifest.json",
5
5
  "surfaces": {
6
6
  "web": {
7
7
  "packageName": "@hjmds/react",
8
- "packageVersion": "1.42.0",
8
+ "packageVersion": "1.43.0",
9
9
  "activeComponents": 131,
10
10
  "claimedComponents": 131,
11
11
  "completeScenarioComponents": 130,
@@ -7063,7 +7063,7 @@
7063
7063
  },
7064
7064
  "native": {
7065
7065
  "packageName": "@hjmds/react-native",
7066
- "packageVersion": "1.42.0",
7066
+ "packageVersion": "1.43.0",
7067
7067
  "activeComponents": 113,
7068
7068
  "claimedComponents": 113,
7069
7069
  "completeScenarioComponents": 110,
@@ -1,6 +1,6 @@
1
1
  # Renderer evidence coverage
2
2
 
3
- > Generated for HJM 1.42.0. Do not edit directly; run `pnpm evidence:sync`.
3
+ > Generated for HJM 1.43.0. Do not edit directly; run `pnpm evidence:sync`.
4
4
 
5
5
  This projection joins the canonical surface maturity manifest with first-party renderer claims. Missing scenarios are explicit beta promotion debt; stable surfaces are blocked by CI until none remain.
6
6
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schemaVersion": 2,
3
- "designSystemVersion": "1.42.0",
3
+ "designSystemVersion": "1.43.0",
4
4
  "packageName": "@hjmds/design-contracts",
5
5
  "components": [
6
6
  {
@@ -7,7 +7,7 @@
7
7
  [선택 기준](SELECTION.md)으로 그대로 사용·공개 슬롯 확장·공통 API 보완·제품 고유 기능 연결을 고른다. 설치 버전의 지침을 본다: `node_modules/@hjmds/design-contracts/docs/usage/`.
8
8
  이름을 모르면 [쉬운 말로 찾고 비교하기](FINDING.md)에서 일상 표현과 선택 기준·요청 예시로 시작한다.
9
9
  제공 기준은 확인한 기본 API 버전이며 최초 출시 버전이 아니다. 구성·화면은 각 API 지침의 제공 버전을 확인한다.
10
- API 안정성은 1.41.2의 생성 manifest에서 읽은 정규(canonical) API 기준이다. 동반·선택형 확장은 개별 계약을 확인한다.
10
+ API 안정성은 1.42.1의 생성 manifest에서 읽은 정규(canonical) API 기준이다. 동반·선택형 확장은 개별 계약을 확인한다.
11
11
  Storybook 배포/실험은 예제 분류이며 npm 게시·기기 검증·제품 반영을 의미하지 않는다.
12
12
  `분류`는 Storybook 제목 `<배포|실험>/<단계>/<분류>/<항목>`의 셋째 마디이고, 토큰·구성·화면은 Storybook 메뉴와 같은 순서다.
13
13
 
@@ -60,6 +60,12 @@ Storybook 배포/실험은 예제 분류이며 npm 게시·기기 검증·제품
60
60
  | [Chart](components/chart.md) | 데이터 표시 | 수치의 흐름·비교·몫·모양·관계를 그림으로 읽게 할 때 쓴다. | 1.21.0 | Web · Native | Web beta / Native beta | 배포 |
61
61
  | [ChatDateSeparator](components/chat-date-separator.md) | 데이터 표시 | 대화 타임라인에서 날짜(또는 오래 쉰 뒤의 시각)가 바뀌는 자리에 가운데 정렬 구분 줄을 둘 때 쓴다. | 1.31.0 | Web · Native | Web beta / Native beta | 배포 |
62
62
  | [ChatMessage](components/chat-message.md) | 데이터 표시 | DM·대화 타임라인의 메시지 한 개에 쓴다. | 1.17.1 | Web · Native | Web stable / Native stable | 배포 |
63
+ | [ChatRoomActions](components/chat-room-actions.md) | 구성/입력과 작성 | 나가기·내 기록 삭제·방 삭제를 구분해 확인한다. | 1.43.0 | Web · Native | 개별 API 계약 참조 | 배포 |
64
+ | [ChatRoomCreate](components/chat-room-create.md) | 구성/입력과 작성 | 참여자를 검색·선택하고 사진·이름을 정해 방을 개설한다. | 1.43.0 | Web · Native | 개별 API 계약 참조 | 배포 |
65
+ | [ChatRoomDetails](components/chat-room-details.md) | 구성/입력과 작성 | 방 프로필·도구·참여자·관리 행동을 묶음형 정보 화면으로 보여 준다. | 1.43.0 | Web · Native | 개별 API 계약 참조 | 배포 |
66
+ | [ChatRoomInvite](components/chat-room-invite.md) | 구성/입력과 작성 | 선택한 새 참여자의 실제 초대 결과를 기다린다. | 1.43.0 | Web · Native | 개별 API 계약 참조 | 배포 |
67
+ | [ChatRoomMembers](components/chat-room-members.md) | 구성/입력과 작성 | 참여자를 표시하고 선택 또는 권한별 메뉴를 제공한다. | 1.43.0 | Web · Native | 개별 API 계약 참조 | 배포 |
68
+ | [ChatRoomProfile](components/chat-room-profile.md) | 구성/입력과 작성 | 사진·이름·소개를 편집하고 실제 저장 결과를 기다린다. | 1.43.0 | Web · Native | 개별 API 계약 참조 | 배포 |
63
69
  | [ChatScreen](components/chat-screen.md) | 레이아웃 | DM·대화방처럼 헤더, 메시지 타임라인, 하단 작성창으로 이루어진 화면 한 장에 쓴다. | 1.17.1 | Web · Native | Web stable / Native stable | 배포 |
64
70
  | [Checkbox](components/checkbox.md) | 입력 | 독립된 예/아니오 하나를 고르는 항목에 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
65
71
  | [CheckboxGroup](components/checkbox-group.md) | 입력 | 한 질문에 대한 여러 선택지 중 0개 이상을 고르게 할 때 쓴다. | 1.12.1 | Web · Native | Web stable / Native stable | 배포 |
@@ -234,6 +240,7 @@ Storybook 배포/실험은 예제 분류이며 npm 게시·기기 검증·제품
234
240
  | [인증번호 확인과 다시 입력](compositions/stea-otp-verify.md) | 입력과 작성 | 문자·메일로 받은 숫자 인증번호를 입력하고 서버 확인을 기다린 뒤, 틀리면 남은 횟수를 보여 주고 다시 받게 하는 흐름에 쓴다. | 1.12.1 | Web · Native | 구성 API별 | 배포 |
235
241
  | [입력 시트](compositions/input-sheet.md) | 입력과 작성 | 현재 화면 위에 하단 시트를 띄워 짧은 입력(이름 바꾸기, 메모 한 줄)을 받고, 키보드가 올라와도 본문을 스크롤하며 완료 버튼에 닿게 할 때 쓴다. | 1.12.1 | Web · Native | 구성 API별 | 배포 |
236
242
  | [입력을 유지하는 도구](compositions/context-toolbar.md) | 입력과 작성 | 작성 중인 입력을 보존한 채 선택적 도구를 펼쳐야 할 때 쓴다. | 1.14.0 | Web · Native | 구성 API별 | 배포 |
243
+ | [채팅방 관리](compositions/chat-room.md) | 입력과 작성 | `@hjmds/react/communication`, `@hjmds/react-native/communication`에서 제공한다. | 1.43.0 | Web · Native | 구성 API별 | 배포 |
237
244
  | [첫 작업을 만들고 이어하기](compositions/reference-first.md) | 입력과 작성 | 첫 기록을 단계별 작성하고 중단한 초안 이어가기 흐름이 필요할 때 쓴다. | 구성 API 지침 참조 | Web · Native | 구성 API별 | 배포 |
238
245
  | [날짜 선택과 예정 목록](compositions/stea-schedule-card.md) | 선택과 필터 | 한 주처럼 짧은 날짜 범위에서 날짜 하나를 고르면 같은 카드 안의 일정 목록이 그 날짜로 바뀌는 요약 카드에 쓴다. | 1.12.1 | Web · Native | 구성 API별 | 배포 |
239
246
  | [날짜와 시각 선택](compositions/date-time-selection.md) | 선택과 필터 | 기록·알림의 날짜 하나와 하루 안의 시각을 함께 고를 때 쓴다. | 1.16.0 | Web · Native | 구성 API별 | 배포 |
@@ -70,6 +70,11 @@ import { Text } from "@hjmds/react-native/primitives";
70
70
  2026-10-16 사용자 결정으로 대화 타임라인의 공통 기준을 카카오톡 iOS 채팅방 실측(@3x 캡처)으로 바꿨다.
71
71
  묶음 단위 표시·촘촘한 말풍선·시각 위치를 흡수했고 노란 말풍선 같은 브랜드 색은 가져오지 않았다(색은 semantic token).
72
72
 
73
+ 수신 말풍선 본체·꼬리와 입력 중 표시는 `surfaceAlt`, 발신은 `primary`와 `onPrimary`를 사용한다. 발신 내부 HJM Text의 중립 tone은 밝은 글자를 상속하고 명시적 색·브랜드·위험 tone은 보존한다.
74
+ 답글 원문은 3px 세로 강조선과 8px 안쪽 간격으로 구분한다(수신 `contentBrand`, 발신 `onPrimary`).
75
+ 아이메시지의 수신/발신 표면 대비와 텔레그램의 인용 강조를 참고했다: https://support.apple.com/guide/iphone/about-imessage-iph4e9799206/ios · https://telegram.org/blog/reply-revolution
76
+ 2026-10-23 밝은 기본 테마에서 `surface`와 채팅 배경이 모두 흰색이라 수신 말풍선이 사라진 문제를 수정했다.
77
+
73
78
  ## 축과 기본값
74
79
 
75
80
  | prop | 값 | 기본값 | 설명 |
@@ -0,0 +1,58 @@
1
+ # ChatRoomActions
2
+
3
+ - 단계: 컴포넌트
4
+ - 상태: 배포
5
+ - 지원: Web · Native
6
+ - 적용: 1.43.0
7
+ - 검토일: 2026-10-23
8
+ - 근거: 양 renderer `src/communication.tsx`와 [채팅방 비교·구성 지침](../compositions/chat-room.md)
9
+ - 스토리북: `배포/구성/입력과 작성/채팅방 관리`
10
+
11
+ ## 언제 쓰나
12
+
13
+ 나가기·내 기록 삭제·방 삭제를 구분해 확인한다.
14
+
15
+ ## 쓰지 않을 때
16
+
17
+ | 상황 | 대신 쓸 것 |
18
+ | --- | --- |
19
+ | 메시지 기록과 작성창만 필요한 화면 | [ChatScreen](chat-screen.md) |
20
+ | 제품의 서버·권한·저장 규칙 구현 | 제품 데이터 계층 |
21
+
22
+ ## 공개 이름과 import
23
+
24
+ | 이름 | 역할 | Web | Native |
25
+ | --- | --- | --- | --- |
26
+ | `ChatRoomActions` | 나가기·내 기록 삭제·방 삭제를 구분해 확인한다. | `@hjmds/react/communication` | `@hjmds/react-native/communication` |
27
+
28
+ ## 최소 사용 예
29
+
30
+ ```tsx
31
+ // Web
32
+ import { ChatRoomActions } from "@hjmds/react/communication";
33
+ <ChatRoomActions leave={leaveConfirmation} deleteHistory={historyConfirmation} />
34
+ ```
35
+
36
+ ```tsx
37
+ // Native
38
+ import { ChatRoomActions } from "@hjmds/react-native/communication";
39
+ <ChatRoomActions leave={leaveConfirmation} deleteHistory={historyConfirmation} />
40
+ ```
41
+
42
+ Native는 동일 prop 계약으로 `@hjmds/react-native/communication`에서 가져온다. 전체 실행 예제와 연결 props는 [채팅방 관리](../compositions/chat-room.md)의 양 플랫폼 예제를 따른다.
43
+
44
+ ## 배치
45
+
46
+ | 항목 | 값 | 근거 |
47
+ | --- | --- | --- |
48
+ | 크기 | 부모 본문 폭, 프로필 Avatar 64·참여자 40 | 기존 Avatar·ListRow recipe |
49
+ | 간격 | 내부 sm·입력 md·그룹 lg | 양 renderer 공통 구성 |
50
+ | 순서·정렬 | 상단 탐색·확인 → 작업 본문 → 오류 | 구성 소스 |
51
+ | 고정·스크롤 | 스크롤·키보드 처리는 host 소유 | 웹·Native의 화면 host 계약 |
52
+ | 좁은 폭 | 도구 동폭, 이름·설명 줄바꿈 | 공통 레이아웃 |
53
+
54
+ ## 꼭 지킬 것
55
+
56
+ leave·deleteHistory·deleteRoom은 독립 선택 prop이다. label·title·description·confirmLabel·cancelLabel·errorLabel·onConfirm을 전달한다.
57
+
58
+ 데이터·문구·권한은 제품이 소유한다. 저장·개설·초대·삭제는 실제 성공 뒤 Promise를 resolve하고 실패는 reject한다. 입력과 선택은 실패 시 유지한다. Storybook의 메모리 예제를 운영 저장으로 사용하지 않는다. 방 전환 시 `key={roomId}`로 작업 수명을 구분한다.
@@ -0,0 +1,58 @@
1
+ # ChatRoomCreate
2
+
3
+ - 단계: 컴포넌트
4
+ - 상태: 배포
5
+ - 지원: Web · Native
6
+ - 적용: 1.43.0
7
+ - 검토일: 2026-10-23
8
+ - 근거: 양 renderer `src/communication.tsx`와 [채팅방 비교·구성 지침](../compositions/chat-room.md)
9
+ - 스토리북: `배포/구성/입력과 작성/채팅방 관리`
10
+
11
+ ## 언제 쓰나
12
+
13
+ 참여자를 검색·선택하고 사진·이름을 정해 방을 개설한다.
14
+
15
+ ## 쓰지 않을 때
16
+
17
+ | 상황 | 대신 쓸 것 |
18
+ | --- | --- |
19
+ | 메시지 기록과 작성창만 필요한 화면 | [ChatScreen](chat-screen.md) |
20
+ | 제품의 서버·권한·저장 규칙 구현 | 제품 데이터 계층 |
21
+
22
+ ## 공개 이름과 import
23
+
24
+ | 이름 | 역할 | Web | Native |
25
+ | --- | --- | --- | --- |
26
+ | `ChatRoomCreate` | 참여자를 검색·선택하고 사진·이름을 정해 방을 개설한다. | `@hjmds/react/communication` | `@hjmds/react-native/communication` |
27
+
28
+ ## 최소 사용 예
29
+
30
+ ```tsx
31
+ // Web
32
+ import { ChatRoomCreate } from "@hjmds/react/communication";
33
+ <ChatRoomCreate {...roomDraftProps} {...memberSelectionProps} {...navigationLabels} onCreate={createRoom} />
34
+ ```
35
+
36
+ ```tsx
37
+ // Native
38
+ import { ChatRoomCreate } from "@hjmds/react-native/communication";
39
+ <ChatRoomCreate {...roomDraftProps} {...memberSelectionProps} {...navigationLabels} onCreate={createRoom} />
40
+ ```
41
+
42
+ Native는 동일 prop 계약으로 `@hjmds/react-native/communication`에서 가져온다. 전체 실행 예제와 연결 props는 [채팅방 관리](../compositions/chat-room.md)의 양 플랫폼 예제를 따른다.
43
+
44
+ ## 배치
45
+
46
+ | 항목 | 값 | 근거 |
47
+ | --- | --- | --- |
48
+ | 크기 | 부모 본문 폭, 프로필 Avatar 64·참여자 40 | 기존 Avatar·ListRow recipe |
49
+ | 간격 | 내부 sm·입력 md·그룹 lg | 양 renderer 공통 구성 |
50
+ | 순서·정렬 | 상단 탐색·확인 → 작업 본문 → 오류 | 구성 소스 |
51
+ | 고정·스크롤 | 스크롤·키보드 처리는 host 소유 | 웹·Native의 화면 host 계약 |
52
+ | 좁은 폭 | 도구 동폭, 이름·설명 줄바꿈 | 공통 레이아웃 |
53
+
54
+ ## 꼭 지킬 것
55
+
56
+ 선택 없이 다음으로 갈 수 없고 빈 이름으로 개설할 수 없다. onCreate는 실제 구성원 ID와 프로필을 받는다.
57
+
58
+ 데이터·문구·권한은 제품이 소유한다. 저장·개설·초대·삭제는 실제 성공 뒤 Promise를 resolve하고 실패는 reject한다. 입력과 선택은 실패 시 유지한다. Storybook의 메모리 예제를 운영 저장으로 사용하지 않는다. 방 전환 시 `key={roomId}`로 작업 수명을 구분한다.
@@ -0,0 +1,58 @@
1
+ # ChatRoomDetails
2
+
3
+ - 단계: 컴포넌트
4
+ - 상태: 배포
5
+ - 지원: Web · Native
6
+ - 적용: 1.43.0
7
+ - 검토일: 2026-10-23
8
+ - 근거: 양 renderer `src/communication.tsx`와 [채팅방 비교·구성 지침](../compositions/chat-room.md)
9
+ - 스토리북: `배포/구성/입력과 작성/채팅방 관리`
10
+
11
+ ## 언제 쓰나
12
+
13
+ 방 프로필·도구·참여자·관리 행동을 묶음형 정보 화면으로 보여 준다.
14
+
15
+ ## 쓰지 않을 때
16
+
17
+ | 상황 | 대신 쓸 것 |
18
+ | --- | --- |
19
+ | 메시지 기록과 작성창만 필요한 화면 | [ChatScreen](chat-screen.md) |
20
+ | 제품의 서버·권한·저장 규칙 구현 | 제품 데이터 계층 |
21
+
22
+ ## 공개 이름과 import
23
+
24
+ | 이름 | 역할 | Web | Native |
25
+ | --- | --- | --- | --- |
26
+ | `ChatRoomDetails` | 방 프로필·도구·참여자·관리 행동을 묶음형 정보 화면으로 보여 준다. | `@hjmds/react/communication` | `@hjmds/react-native/communication` |
27
+
28
+ ## 최소 사용 예
29
+
30
+ ```tsx
31
+ // Web
32
+ import { ChatRoomDetails } from "@hjmds/react/communication";
33
+ <ChatRoomDetails profile={room} photoLabel="채팅방 사진" memberCountLabel={memberCountLabel} members={memberListProps} errorLabel="작업을 완료하지 못했어요." />
34
+ ```
35
+
36
+ ```tsx
37
+ // Native
38
+ import { ChatRoomDetails } from "@hjmds/react-native/communication";
39
+ <ChatRoomDetails profile={room} photoLabel="채팅방 사진" memberCountLabel={memberCountLabel} members={memberListProps} errorLabel="작업을 완료하지 못했어요." />
40
+ ```
41
+
42
+ Native는 동일 prop 계약으로 `@hjmds/react-native/communication`에서 가져온다. 전체 실행 예제와 연결 props는 [채팅방 관리](../compositions/chat-room.md)의 양 플랫폼 예제를 따른다.
43
+
44
+ ## 배치
45
+
46
+ | 항목 | 값 | 근거 |
47
+ | --- | --- | --- |
48
+ | 크기 | 부모 본문 폭, 프로필 Avatar 64·참여자 40 | 기존 Avatar·ListRow recipe |
49
+ | 간격 | 내부 sm·입력 md·그룹 lg | 양 renderer 공통 구성 |
50
+ | 순서·정렬 | 상단 탐색·확인 → 작업 본문 → 오류 | 구성 소스 |
51
+ | 고정·스크롤 | 스크롤·키보드 처리는 host 소유 | 웹·Native의 화면 host 계약 |
52
+ | 좁은 폭 | 도구 동폭, 이름·설명 줄바꿈 | 공통 레이아웃 |
53
+
54
+ ## 꼭 지킬 것
55
+
56
+ profile·photoLabel·memberCountLabel·members·errorLabel이 필수다. edit·tools·actions는 권한과 제품 경로가 있는 경우 전달한다.
57
+
58
+ 데이터·문구·권한은 제품이 소유한다. 저장·개설·초대·삭제는 실제 성공 뒤 Promise를 resolve하고 실패는 reject한다. 입력과 선택은 실패 시 유지한다. Storybook의 메모리 예제를 운영 저장으로 사용하지 않는다. 방 전환 시 `key={roomId}`로 작업 수명을 구분한다.
@@ -0,0 +1,58 @@
1
+ # ChatRoomInvite
2
+
3
+ - 단계: 컴포넌트
4
+ - 상태: 배포
5
+ - 지원: Web · Native
6
+ - 적용: 1.43.0
7
+ - 검토일: 2026-10-23
8
+ - 근거: 양 renderer `src/communication.tsx`와 [채팅방 비교·구성 지침](../compositions/chat-room.md)
9
+ - 스토리북: `배포/구성/입력과 작성/채팅방 관리`
10
+
11
+ ## 언제 쓰나
12
+
13
+ 선택한 새 참여자의 실제 초대 결과를 기다린다.
14
+
15
+ ## 쓰지 않을 때
16
+
17
+ | 상황 | 대신 쓸 것 |
18
+ | --- | --- |
19
+ | 메시지 기록과 작성창만 필요한 화면 | [ChatScreen](chat-screen.md) |
20
+ | 제품의 서버·권한·저장 규칙 구현 | 제품 데이터 계층 |
21
+
22
+ ## 공개 이름과 import
23
+
24
+ | 이름 | 역할 | Web | Native |
25
+ | --- | --- | --- | --- |
26
+ | `ChatRoomInvite` | 선택한 새 참여자의 실제 초대 결과를 기다린다. | `@hjmds/react/communication` | `@hjmds/react-native/communication` |
27
+
28
+ ## 최소 사용 예
29
+
30
+ ```tsx
31
+ // Web
32
+ import { ChatRoomInvite } from "@hjmds/react/communication";
33
+ <ChatRoomInvite {...memberSelectionProps} onInvite={inviteMembers} confirmLabel="초대하기" errorLabel="초대하지 못했어요." />
34
+ ```
35
+
36
+ ```tsx
37
+ // Native
38
+ import { ChatRoomInvite } from "@hjmds/react-native/communication";
39
+ <ChatRoomInvite {...memberSelectionProps} onInvite={inviteMembers} confirmLabel="초대하기" errorLabel="초대하지 못했어요." />
40
+ ```
41
+
42
+ Native는 동일 prop 계약으로 `@hjmds/react-native/communication`에서 가져온다. 전체 실행 예제와 연결 props는 [채팅방 관리](../compositions/chat-room.md)의 양 플랫폼 예제를 따른다.
43
+
44
+ ## 배치
45
+
46
+ | 항목 | 값 | 근거 |
47
+ | --- | --- | --- |
48
+ | 크기 | 부모 본문 폭, 프로필 Avatar 64·참여자 40 | 기존 Avatar·ListRow recipe |
49
+ | 간격 | 내부 sm·입력 md·그룹 lg | 양 renderer 공통 구성 |
50
+ | 순서·정렬 | 상단 탐색·확인 → 작업 본문 → 오류 | 구성 소스 |
51
+ | 고정·스크롤 | 스크롤·키보드 처리는 host 소유 | 웹·Native의 화면 host 계약 |
52
+ | 좁은 폭 | 도구 동폭, 이름·설명 줄바꿈 | 공통 레이아웃 |
53
+
54
+ ## 꼭 지킬 것
55
+
56
+ members·title·emptyLabel·onSelectionChange·onInvite·confirmLabel·errorLabel이 필수다. disabled 멤버는 요청에서 제외한다.
57
+
58
+ 데이터·문구·권한은 제품이 소유한다. 저장·개설·초대·삭제는 실제 성공 뒤 Promise를 resolve하고 실패는 reject한다. 입력과 선택은 실패 시 유지한다. Storybook의 메모리 예제를 운영 저장으로 사용하지 않는다. 방 전환 시 `key={roomId}`로 작업 수명을 구분한다.
@@ -0,0 +1,58 @@
1
+ # ChatRoomMembers
2
+
3
+ - 단계: 컴포넌트
4
+ - 상태: 배포
5
+ - 지원: Web · Native
6
+ - 적용: 1.43.0
7
+ - 검토일: 2026-10-23
8
+ - 근거: 양 renderer `src/communication.tsx`와 [채팅방 비교·구성 지침](../compositions/chat-room.md)
9
+ - 스토리북: `배포/구성/입력과 작성/채팅방 관리`
10
+
11
+ ## 언제 쓰나
12
+
13
+ 참여자를 표시하고 선택 또는 권한별 메뉴를 제공한다.
14
+
15
+ ## 쓰지 않을 때
16
+
17
+ | 상황 | 대신 쓸 것 |
18
+ | --- | --- |
19
+ | 메시지 기록과 작성창만 필요한 화면 | [ChatScreen](chat-screen.md) |
20
+ | 제품의 서버·권한·저장 규칙 구현 | 제품 데이터 계층 |
21
+
22
+ ## 공개 이름과 import
23
+
24
+ | 이름 | 역할 | Web | Native |
25
+ | --- | --- | --- | --- |
26
+ | `ChatRoomMembers` | 참여자를 표시하고 선택 또는 권한별 메뉴를 제공한다. | `@hjmds/react/communication` | `@hjmds/react-native/communication` |
27
+
28
+ ## 최소 사용 예
29
+
30
+ ```tsx
31
+ // Web
32
+ import { ChatRoomMembers } from "@hjmds/react/communication";
33
+ <ChatRoomMembers members={members} title="참여자" emptyLabel="참여자가 없습니다." />
34
+ ```
35
+
36
+ ```tsx
37
+ // Native
38
+ import { ChatRoomMembers } from "@hjmds/react-native/communication";
39
+ <ChatRoomMembers members={members} title="참여자" emptyLabel="참여자가 없습니다." />
40
+ ```
41
+
42
+ Native는 동일 prop 계약으로 `@hjmds/react-native/communication`에서 가져온다. 전체 실행 예제와 연결 props는 [채팅방 관리](../compositions/chat-room.md)의 양 플랫폼 예제를 따른다.
43
+
44
+ ## 배치
45
+
46
+ | 항목 | 값 | 근거 |
47
+ | --- | --- | --- |
48
+ | 크기 | 부모 본문 폭, 프로필 Avatar 64·참여자 40 | 기존 Avatar·ListRow recipe |
49
+ | 간격 | 내부 sm·입력 md·그룹 lg | 양 renderer 공통 구성 |
50
+ | 순서·정렬 | 상단 탐색·확인 → 작업 본문 → 오류 | 구성 소스 |
51
+ | 고정·스크롤 | 스크롤·키보드 처리는 host 소유 | 웹·Native의 화면 host 계약 |
52
+ | 좁은 폭 | 도구 동폭, 이름·설명 줄바꿈 | 공통 레이아웃 |
53
+
54
+ ## 꼭 지킬 것
55
+
56
+ members·title·emptyLabel이 필수다. onSelectionChange가 있으면 선택 목록이다. actions에는 허용된 행동만 전달한다.
57
+
58
+ 데이터·문구·권한은 제품이 소유한다. 저장·개설·초대·삭제는 실제 성공 뒤 Promise를 resolve하고 실패는 reject한다. 입력과 선택은 실패 시 유지한다. Storybook의 메모리 예제를 운영 저장으로 사용하지 않는다. 방 전환 시 `key={roomId}`로 작업 수명을 구분한다.
@@ -0,0 +1,58 @@
1
+ # ChatRoomProfile
2
+
3
+ - 단계: 컴포넌트
4
+ - 상태: 배포
5
+ - 지원: Web · Native
6
+ - 적용: 1.43.0
7
+ - 검토일: 2026-10-23
8
+ - 근거: 양 renderer `src/communication.tsx`와 [채팅방 비교·구성 지침](../compositions/chat-room.md)
9
+ - 스토리북: `배포/구성/입력과 작성/채팅방 관리`
10
+
11
+ ## 언제 쓰나
12
+
13
+ 사진·이름·소개를 편집하고 실제 저장 결과를 기다린다.
14
+
15
+ ## 쓰지 않을 때
16
+
17
+ | 상황 | 대신 쓸 것 |
18
+ | --- | --- |
19
+ | 메시지 기록과 작성창만 필요한 화면 | [ChatScreen](chat-screen.md) |
20
+ | 제품의 서버·권한·저장 규칙 구현 | 제품 데이터 계층 |
21
+
22
+ ## 공개 이름과 import
23
+
24
+ | 이름 | 역할 | Web | Native |
25
+ | --- | --- | --- | --- |
26
+ | `ChatRoomProfile` | 사진·이름·소개를 편집하고 실제 저장 결과를 기다린다. | `@hjmds/react/communication` | `@hjmds/react-native/communication` |
27
+
28
+ ## 최소 사용 예
29
+
30
+ ```tsx
31
+ // Web
32
+ import { ChatRoomProfile } from "@hjmds/react/communication";
33
+ <ChatRoomProfile value={draft} onValueChange={setDraft} onSave={saveProfile} labels={labels} />
34
+ ```
35
+
36
+ ```tsx
37
+ // Native
38
+ import { ChatRoomProfile } from "@hjmds/react-native/communication";
39
+ <ChatRoomProfile value={draft} onValueChange={setDraft} onSave={saveProfile} labels={labels} />
40
+ ```
41
+
42
+ Native는 동일 prop 계약으로 `@hjmds/react-native/communication`에서 가져온다. 전체 실행 예제와 연결 props는 [채팅방 관리](../compositions/chat-room.md)의 양 플랫폼 예제를 따른다.
43
+
44
+ ## 배치
45
+
46
+ | 항목 | 값 | 근거 |
47
+ | --- | --- | --- |
48
+ | 크기 | 부모 본문 폭, 프로필 Avatar 64·참여자 40 | 기존 Avatar·ListRow recipe |
49
+ | 간격 | 내부 sm·입력 md·그룹 lg | 양 renderer 공통 구성 |
50
+ | 순서·정렬 | 상단 탐색·확인 → 작업 본문 → 오류 | 구성 소스 |
51
+ | 고정·스크롤 | 스크롤·키보드 처리는 host 소유 | 웹·Native의 화면 host 계약 |
52
+ | 좁은 폭 | 도구 동폭, 이름·설명 줄바꿈 | 공통 레이아웃 |
53
+
54
+ ## 꼭 지킬 것
55
+
56
+ value·onValueChange·onSave·labels가 필수다. onPickPhoto는 업로드한 URL을 반환하며 null은 취소다.
57
+
58
+ 데이터·문구·권한은 제품이 소유한다. 저장·개설·초대·삭제는 실제 성공 뒤 Promise를 resolve하고 실패는 reject한다. 입력과 선택은 실패 시 유지한다. Storybook의 메모리 예제를 운영 저장으로 사용하지 않는다. 방 전환 시 `key={roomId}`로 작업 수명을 구분한다.
@@ -0,0 +1,110 @@
1
+ # 채팅방 관리
2
+
3
+ - 단계: 구성
4
+ - 상태: 배포
5
+ - 지원: Web · Native
6
+ - 적용: 1.43.0
7
+ - 검토일: 2026-10-23
8
+ - 근거: Telegram·Signal 실제 화면 비교와 채팅방 관리 공통화 요청
9
+ - 스토리북: `배포/구성/입력과 작성/채팅방 관리`
10
+
11
+ ## 언제 쓰나
12
+
13
+ `@hjmds/react/communication`, `@hjmds/react-native/communication`에서 제공한다.
14
+ 기존 ChatScreen은 메시지 기록·작성창의 화면 틀이다. 이 구성은 방 정보·개설·멤버 관리라는 별도 작업을 소유하며, ChatScreen 헤더의 방 정보 행동에서 연다.
15
+
16
+ ## 구성 요소
17
+
18
+ | 컴포넌트 | 역할 | 지침 |
19
+ | --- | --- | --- |
20
+ | Avatar | 방·참여자 사진 | [Avatar](../components/avatar.md) |
21
+ | TextField | 이름·소개 초안 | [TextField](../components/text-field.md) |
22
+ | Menu | 멤버별 허용 행동 | [Menu](../components/menu.md) |
23
+ | AlertDialog | 나가기·삭제·권한 변경 확인 | [AlertDialog](../components/alert-dialog.md) |
24
+
25
+ - `ChatRoomDetails`: 가운데 방 사진·이름·인원·소개 → 편집 → 검색·공유 미디어·알림·초대 도구 → 참여자 → 파괴 행동 순서.
26
+ - `ChatRoomProfile`: 사진 선택/제거 → 이름·소개 → 저장. 제품이 제어하는 draft를 받는다.
27
+ - `ChatRoomCreate`: 참여자 검색·선택 후 사진·이름·소개를 설정하는 두 단계를 제공한다. 빈 이름이나 참여자 없는 생성은 막는다.
28
+ - `ChatRoomMembers`: 아바타·이름·역할 설명, 선택 또는 멤버별 앵커 메뉴. 권한이 있는 행동만 전달한다.
29
+ - `ChatRoomInvite`: 아직 참여하지 않은 사람을 선택하고 초대한다. disabled 멤버는 요청에서 제외한다.
30
+ - `ChatRoomActions`: 내 기록 삭제, 방 나가기, 방 자체 삭제를 별도 확인으로 처리한다. 관리 권한이 없는 삭제는 전달하지 않는다.
31
+
32
+ ## 배치
33
+
34
+ | 영역 | 컴포넌트 | 위치 | 크기·간격 |
35
+ | --- | --- | --- | --- |
36
+ | 바깥 틀 | Stack | 부모 화면 본문 | gap xl |
37
+ | 방 정보 | Avatar·Text | 상단 중앙 | Avatar xlarge 64, gap sm |
38
+ | 참여자 | Avatar·Checkbox·Menu | 본문 | gap md |
39
+ | 나가기·삭제 | ListRow·AlertDialog | 최하단 | 기존 row recipe |
40
+
41
+ ```text
42
+ [방 사진 xlarge: 64]
43
+ 방 이름 · 인원
44
+ [뒤로] [정보 편집]
45
+ 소개
46
+ [검색] [사진·파일] [알림] [초대]
47
+ 참여자
48
+ [사진] 이름 · 역할 [메뉴]
49
+ 채팅방 나가기
50
+ 내 대화 기록 삭제
51
+ ```
52
+
53
+ Stack gap은 그룹 `xl`, 입력/목록 `md`, 내부 `sm`이다. Avatar·Button·ListRow·Menu·AlertDialog의 기존 recipe를 재사용한다.
54
+ 최종 삭제 확인은 danger AlertDialog이며 취소·pending·실패·중복 확인 방지는 기존 공통 동작을 따른다.
55
+
56
+ ## 흐름과 상태
57
+
58
+ | 상태 | 모습 | 포커스·알림 |
59
+ | --- | --- | --- |
60
+ | 기본 | 방 정보와 권한별 도구 | 화면 host가 진입을 소유 |
61
+ | 진행 중 | 요청 버튼 busy, 편집 잠금 | 중복 요청 방지 |
62
+ | 실패 | 입력 유지, 오류 문구 | alert 안내 후 재시도 가능 |
63
+
64
+ 1. 방 정보에서 편집 또는 초대를 연다.
65
+ 2. 제품이 사진·이름·멤버 초안을 제어한다.
66
+ 3. 성공 응답 뒤 제품이 닫기·이동을 결정한다.
67
+
68
+ 사진 선택/업로드는 `onPickPhoto`에서 제품이 수행하고 저장 가능한 URL을 반환한다. 취소는 null이다. 미디어 권한·서버 업로드를 HJM이 추정하지 않는다. `onValueChange`는 초안 변경, `onSave`/`onCreate`/`onInvite`의 resolve는 서버 성공을 뜻한다. 실패는 reject하며 초안을 지우지 않는다. 서버 결과를 받은 제품이 닫힘·이동·성공 안내를 결정한다.
69
+
70
+ 방을 바꿀 때 구성에 `key={roomId}`를 지정한다. 방 데이터·사진 URL·구성원 ID·역할·지역화 문구·권한과 마지막 관리자 이탈 정책은 제품이 소유한다. 서버에서도 권한을 검증해야 한다. 모든 버튼을 노출하는 권한 기본값은 없다.
71
+ `deleteHistory`는 내 기록 삭제, `leave`는 멤버십 탈퇴, `deleteRoom`은 전체 방 삭제다. 하나를 다른 기능의 대체로 연결하지 않는다.
72
+ 검색/공유 미디어/알림은 `tools`가 실제 제품 경로로 연결한다. 검색 엔진이나 알림 서버가 이 구성에 포함됐다는 뜻이 아니다.
73
+
74
+ ## 코드 골격
75
+
76
+ ```tsx
77
+ // Web
78
+ <ChatRoomProfile key={roomId} value={draft} onValueChange={setDraft}
79
+ onSave={saveRoomProfile} onPickPhoto={pickAndUploadRoomPhoto} labels={labels} />
80
+ ```
81
+
82
+ ```tsx
83
+ // Native
84
+ <ChatRoomProfile key={roomId} value={draft} onValueChange={setDraft}
85
+ onSave={saveRoomProfile} onPickPhoto={pickAndUploadRoomPhoto} labels={labels} />
86
+ ```
87
+
88
+ 실행 가능한 Web 예제: `showcase/web/src/patterns/ChatRoom.preview.tsx`.
89
+ Native 예제: `showcase/native/src/ChatRoom.preview.tsx`.
90
+ 기본·정보 편집·단톡방 개설·실패 후 입력 유지·멤버 권한·어두운 테마를 제공한다. 예제의 사진 선택·저장·멤버 변경은 fixture이며 운영 저장이 아니다.
91
+
92
+ ## 참고한 흐름
93
+
94
+ 2026-10-23 사용자 요청에 따라 [Signal 그룹 관리](https://support.signal.org/hc/en-us/articles/360050427692-Manage-a-group)의 사진·이름·소개·관리자 권한과 [Telegram 공유 미디어](https://telegram.org/blog/shared-media-scrolling-calendar-join-requests-and-more)의 방별 미디어 진입을 참고했다. 색·간격·버튼·모달은 HJM과 제품 테마가 소유한다. [Signal 기록 삭제](https://support.signal.org/hc/en-us/articles/360007320491-Delete-messages-alerts-or-chats)를 참고해 기록 삭제와 나가기를 분리했다.
95
+
96
+ ## 실제 화면 비교와 반영 — 2026-10-23
97
+
98
+ 문서의 기능 목록만 읽고 첫 시안을 만든 접근을 사용자가 지적했다. 아래 원본 이미지를 브라우저에서 실제로 열어 HJM 웹 390px·기존 iPhone 17 Pro 화면과 비교하고 구성을 다시 만들었다.
99
+
100
+ | 비교 화면 | HJM에서 확인한 차이 | 공통 구현에 흡수한 내용 |
101
+ | --- | --- | --- |
102
+ | [Telegram 방 정보·편집 화면](https://img7.thuthuatphanmem.vn/uploads/2023/08/29/chon-members_020222519.jpg) | 초기 시안은 2줄 테두리 버튼, 본문 중앙 편집, 지나친 분산 배치 | 상단 편집, 1줄 동폭 아이콘 타일, 묶음형 참여자·설정 영역. 색은 HJM bg·surface 역할 유지 |
103
+ | [Signal 방 개설 화면](https://www.hardreset.info/media/resetinfo/2021/021/da0f9e34575545b8aca274f144ca3ce0/apps-signal.jpg) | 초기 시안은 사진·이름·전체 멤버를 한 화면에 넣고 하단 생성 | 검색 가능한 참여자 선택 → 사진·이름 설정, 상단 다음·개설·뒤로, 선택과 초안 유지 |
104
+ | [Telegram 답글 원본](https://telegram.org/file/400780400216/2/mfF9maKnA2g.67421/e744b36dd0e0da3840) | 인용 영역과 본문 구분이 약함 | 3px 시작선과 12% 인용 표면색, 누르면 원문 이동하는 기존 replyLink 보존 |
105
+ | Signal 그룹 관리 흐름 | 생성·초대·역할 변경이 화면별 조립에 맡겨짐 | ChatRoomCreate·Invite·Members와 서버 성공 대기, 취소·확인·실패 상태 제공 |
106
+ | 현재 대화 목록 예제 | 작성 버튼이 상태 문구만 변경 | 웹·Native의 실제 단톡방 개설 흐름으로 연결 |
107
+
108
+ 사진·검색·미디어·알림·멤버 저장의 실제 서버는 제품이 연결한다. Storybook에서 fixture로 검증한 상태를 제품 운영 기능 완료로 보고하지 않는다. 현재 번뚝은 peer 기반 DM 및 프로젝트 대화, 유틸버스는 단일 도구 대화라 그룹 서버·권한·보존 정책은 별도 제품 구현 지점이다.
109
+
110
+ 2026-10-23 사용자 보완: 다른 앱의 배경색·브랜드 팔레트는 복제하지 않는다. 참조 범위는 기능·배치·상호작용이며 화면 바탕은 HJM `bg`, 그룹·도구는 `surface`, 강조와 글자는 기존 의미 토큰과 제품 Provider를 따른다.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hjmds/design-contracts",
3
- "version": "1.42.0",
3
+ "version": "1.43.0",
4
4
  "description": "Renderer-neutral design contracts, tokens, recipes, and behaviors shared by HJM products.",
5
5
  "license": "MIT",
6
6
  "repository": {