@underdogai/mesh-event-schemas 0.8.0 → 0.9.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/blocks.d.ts CHANGED
@@ -189,6 +189,16 @@ export declare const FieldsBlockSchema: z.ZodObject<{
189
189
  };
190
190
  url?: string | undefined;
191
191
  }>]>>;
192
+ /**
193
+ * **이 항목은 문단이다**(0.9.0) — 값이 아니라 본문. 전체폭으로 서고 값 서체(600)를 풀며
194
+ * 인라인 마크다운을 그린다.
195
+ *
196
+ * 왜 필요한가(감사 문서 D): "막힌 일: ㅁㄴㄹ…" 같은 자유 서술이 지금은 굵은 값 서체로 서서
197
+ * 숫자·상태와 같은 무게로 읽힌다. 작성자가 `short` 로 열 수를 강제하던 것과 같은 자리 —
198
+ * 작성자는 "이건 문단이다"만 말하고 폭·서체는 렌더러가 정한다.
199
+ * ⚠️ `short` 와 같이 주면 `long` 이 이긴다(반폭 문단은 없다).
200
+ */
201
+ long: z.ZodOptional<z.ZodBoolean>;
192
202
  }, "strip", z.ZodTypeAny, {
193
203
  value: string;
194
204
  label: string;
@@ -206,6 +216,7 @@ export declare const FieldsBlockSchema: z.ZodObject<{
206
216
  };
207
217
  url?: string | undefined;
208
218
  } | undefined;
219
+ long?: boolean | undefined;
209
220
  }, {
210
221
  value: string;
211
222
  label: string;
@@ -223,7 +234,17 @@ export declare const FieldsBlockSchema: z.ZodObject<{
223
234
  };
224
235
  url?: string | undefined;
225
236
  } | undefined;
237
+ long?: boolean | undefined;
226
238
  }>, "many">;
239
+ /**
240
+ * 열 수 **명시 오버라이드**(0.9.0). 생략이 기본이고, 기본은 폭이 정하는 auto-fit 이다
241
+ * (그리고 `short` 넷이면 2×2 로 묶인다 — 0.7.0 에서 이미 들어간 규칙).
242
+ *
243
+ * 🔴 **기본을 되돌리지 않는다.** 이 키는 auto-fit 이 틀리는 드문 경우(라벨이 길어 3열이 찢어지는
244
+ * 표 같은 fields)를 위한 탈출구다 — 늘 주면 좁은 화면에서 열이 안 줄어 값이 짜부라진다.
245
+ * `"auto"` 는 명시적으로 기본을 고르는 값이다(작성자가 "여긴 렌더러에 맡긴다"를 적을 수 있게).
246
+ */
247
+ columns: z.ZodOptional<z.ZodUnion<[z.ZodLiteral<2>, z.ZodLiteral<3>, z.ZodLiteral<"auto">]>>;
227
248
  }, "strip", z.ZodTypeAny, {
228
249
  type: "fields";
229
250
  items: {
@@ -243,7 +264,9 @@ export declare const FieldsBlockSchema: z.ZodObject<{
243
264
  };
244
265
  url?: string | undefined;
245
266
  } | undefined;
267
+ long?: boolean | undefined;
246
268
  }[];
269
+ columns?: 2 | 3 | "auto" | undefined;
247
270
  }, {
248
271
  type: "fields";
249
272
  items: {
@@ -263,7 +286,9 @@ export declare const FieldsBlockSchema: z.ZodObject<{
263
286
  };
264
287
  url?: string | undefined;
265
288
  } | undefined;
289
+ long?: boolean | undefined;
266
290
  }[];
291
+ columns?: 2 | 3 | "auto" | undefined;
267
292
  }>;
268
293
  export declare const ImageBlockSchema: z.ZodObject<{
269
294
  type: z.ZodLiteral<"image">;
@@ -500,7 +525,13 @@ export type SliderBlock = z.infer<typeof SliderBlockSchema>;
500
525
  * 욱여넣던 것을 두 줄로 가른다(가독성). 옛 클라는 zod 가 벗겨내므로 라벨만 보인다(하위호환).
501
526
  * `style` = 표현 힌트(선택): "cards" 는 옵션을 전체폭 카드 행으로, "segmented" 는 한 줄 세그먼트로
502
527
  * (짧은 라벨 전용 — 렌더러가 hint 를 숨긴다). 값 의미는 동일하고 옛 클라는 평 라디오로 그린다.
503
- * ⚠️ 위치 선택자(:first-child)로 특정 폼만 다르게 칠하지 말 것 — 표현은 이 필드로 선언한다. */
528
+ * ⚠️ 위치 선택자(:first-child)로 특정 폼만 다르게 칠하지 말 것 — 표현은 이 필드로 선언한다.
529
+ *
530
+ * 📎 **0.9.0 부터 이것은 `select` 의 별칭이다** — `style: "list"` · `multi` 없음 · `source` 없음의
531
+ * `select` 와 **같은 컨트롤로 그려진다**(`spec-renderer/OptionGroup.tsx` 한 벌). 스키마를 합치지
532
+ * 않는 이유는 둘뿐이다: ① 이미 나간 카드가 `type: "radio"` 로 쌓여 있고, ② `style: "cards"` 는
533
+ * 라디오에만 있는 표현이다. 새로 쓰는 카드라면 어느 쪽을 골라도 되고, **선택 축이 하나라도 늘면**
534
+ * (`multi`·`source`·`searchable`) `select` 로 가야 한다 — 그 축들은 여기 없다. */
504
535
  export declare const RadioBlockSchema: z.ZodObject<{
505
536
  type: z.ZodLiteral<"radio">;
506
537
  name: z.ZodString;
@@ -551,6 +582,70 @@ export declare const RadioBlockSchema: z.ZodObject<{
551
582
  error?: string | undefined;
552
583
  style?: "cards" | "segmented" | undefined;
553
584
  }>;
585
+ /**
586
+ * **후보 공급원**(0.9.0) — 후보가 *어디서 오는가*. 생략하면 `options` 배열이 곧 후보다(지금까지의 동작).
587
+ *
588
+ * 왜 축인가: "검색하기" 버튼 + 체크박스 18개 + "사람 더 보기 · 13명" 은 서로 다른 기능이 아니라
589
+ * **후보가 카드 밖에 있을 때** 작성자가 손으로 만든 우회 UI 다(감사 문서 B). 공급원을 선언으로
590
+ * 올리면 검색·스크롤·아바타 행은 렌더러가 정한다.
591
+ *
592
+ * 🔴 **`source` 를 줘도 `options` 는 계약이다.** 이 키를 모르는 옛 클라는 zod strip 으로 벗기고
593
+ * `options` 만 그린다 — 비워 보내면 그 클라에서 **고를 것이 없는 select** 가 선다(`ref` 의 평문
594
+ * 사본과 같은 규칙, `RefSchema` 머리말). 방 멤버는 빌더가 채울 수 없으므로(서버는 방 상태를 모를
595
+ * 수 있다) 그땐 카드 `fallback` 이 대신 설명해야 한다.
596
+ */
597
+ export declare const SelectSourceSchema: z.ZodUnion<[z.ZodObject<{
598
+ /** 이 방의 멤버가 후보다. 값은 MXID 배열이고, 이름·아바타는 클라가 방 상태로 해석한다. */
599
+ kind: z.ZodLiteral<"room">;
600
+ /** 보는 사람 자신을 후보에서 뺀다(기본 false). "받을 사람"처럼 나를 고를 일이 없는 자리. */
601
+ exclude_self: z.ZodOptional<z.ZodBoolean>;
602
+ /** 후보에서 뺄 MXID 목록 — 이미 담당인 사람, 퇴사 처리 중인 계정 등. */
603
+ exclude: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
604
+ /** 봇·에이전트 계정도 후보에 넣는다(기본 false — 사람을 고르는 자리가 대부분이다). */
605
+ include_bots: z.ZodOptional<z.ZodBoolean>;
606
+ }, "strip", z.ZodTypeAny, {
607
+ kind: "room";
608
+ exclude_self?: boolean | undefined;
609
+ exclude?: string[] | undefined;
610
+ include_bots?: boolean | undefined;
611
+ }, {
612
+ kind: "room";
613
+ exclude_self?: boolean | undefined;
614
+ exclude?: string[] | undefined;
615
+ include_bots?: boolean | undefined;
616
+ }>, z.ZodObject<{
617
+ /** 타이핑할 때마다 서버에 묻는다 — 답은 `org.corp.ui.action.result` 의 `kind: "options"`. */
618
+ kind: z.ZodLiteral<"query">;
619
+ /**
620
+ * 질의를 받을 액션. 클라는 `action_type: "query"` 로 `{ q, name }` 을 실어 보낸다.
621
+ * 🔴 사람이 누른 게 아니므로 앱은 **부작용 없이** `ctx.result({ kind: "options", name, options })`
622
+ * 로만 답해야 한다(같은 핸들러가 제출도 처리한다면 `action_type` 으로 갈라야 한다).
623
+ */
624
+ action_id: z.ZodString;
625
+ /** 몇 글자부터 묻나(기본 1). 한 글자에 전체 스캔이 도는 백엔드라면 올린다. */
626
+ min_chars: z.ZodOptional<z.ZodNumber>;
627
+ /** 타이핑이 멎고 몇 ms 뒤에 묻나(기본 300). */
628
+ debounce_ms: z.ZodOptional<z.ZodNumber>;
629
+ }, "strip", z.ZodTypeAny, {
630
+ kind: "query";
631
+ action_id: string;
632
+ min_chars?: number | undefined;
633
+ debounce_ms?: number | undefined;
634
+ }, {
635
+ kind: "query";
636
+ action_id: string;
637
+ min_chars?: number | undefined;
638
+ debounce_ms?: number | undefined;
639
+ }>]>;
640
+ export type SelectSource = z.infer<typeof SelectSourceSchema>;
641
+ /**
642
+ * **하나의 선택 모델**(감사 문서 B) — "후보 집합에서 N 개를 고른다"는 일 하나가 세 축으로 선다:
643
+ * 공급원(`source`) × 개수(`multi`·`min`·`max`) × 표현(`style`·`searchable`).
644
+ *
645
+ * 축이 직교라서 사람 선택도, 검색도, "더 보기"도 **새 블록이 아니라 축의 값**이다. 배치 판정
646
+ * (네이티브냐 콤보박스냐, 칩이냐)은 작성자가 아니라 렌더러가 한다 —
647
+ * `spec-renderer/chooseModel.ts` 의 `choosePlan` 이 그 판정표를 한 자리에서 갖는다.
648
+ */
554
649
  export declare const SelectBlockSchema: z.ZodObject<{
555
650
  type: z.ZodLiteral<"select">;
556
651
  name: z.ZodString;
@@ -558,11 +653,13 @@ export declare const SelectBlockSchema: z.ZodObject<{
558
653
  placeholder: z.ZodOptional<z.ZodString>;
559
654
  /**
560
655
  * 후보 목록. `ref`(0.8.0)를 주면 렌더러가 행을 칩(아바타·이름·MXID)으로 그린다 —
561
- * 🔴 `label` 은 평문 사본으로 남긴다(RefSchema 머리말). 그리는 쪽은 P5(선택 모델)가 맡는다.
656
+ * 🔴 `label` 은 평문 사본으로 남긴다(RefSchema 머리말).
657
+ * `hint`(0.9.0)는 라벨 아래 한 줄 보조 설명 — `radio` 의 같은 이름 키와 같은 뜻이다.
562
658
  */
563
659
  options: z.ZodArray<z.ZodObject<{
564
660
  value: z.ZodString;
565
661
  label: z.ZodString;
662
+ hint: z.ZodOptional<z.ZodString>;
566
663
  ref: z.ZodOptional<z.ZodUnion<[z.ZodObject<{
567
664
  /** Matrix 사용자 id — `@local:server` 형태. 해석(이름·아바타)은 호스트가 주입한다(PeopleProvider). */
568
665
  user: z.ZodString;
@@ -609,6 +706,7 @@ export declare const SelectBlockSchema: z.ZodObject<{
609
706
  };
610
707
  url?: string | undefined;
611
708
  } | undefined;
709
+ hint?: string | undefined;
612
710
  }, {
613
711
  value: string;
614
712
  label: string;
@@ -621,9 +719,67 @@ export declare const SelectBlockSchema: z.ZodObject<{
621
719
  };
622
720
  url?: string | undefined;
623
721
  } | undefined;
722
+ hint?: string | undefined;
624
723
  }>, "many">;
625
724
  value: z.ZodOptional<z.ZodString>;
626
725
  multi: z.ZodOptional<z.ZodBoolean>;
726
+ /** 후보가 어디서 오나 (0.9.0). 생략 = `options` 배열. 위 `SelectSourceSchema` 머리말 참조. */
727
+ source: z.ZodOptional<z.ZodUnion<[z.ZodObject<{
728
+ /** 이 방의 멤버가 후보다. 값은 MXID 배열이고, 이름·아바타는 클라가 방 상태로 해석한다. */
729
+ kind: z.ZodLiteral<"room">;
730
+ /** 보는 사람 자신을 후보에서 뺀다(기본 false). "받을 사람"처럼 나를 고를 일이 없는 자리. */
731
+ exclude_self: z.ZodOptional<z.ZodBoolean>;
732
+ /** 후보에서 뺄 MXID 목록 — 이미 담당인 사람, 퇴사 처리 중인 계정 등. */
733
+ exclude: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
734
+ /** 봇·에이전트 계정도 후보에 넣는다(기본 false — 사람을 고르는 자리가 대부분이다). */
735
+ include_bots: z.ZodOptional<z.ZodBoolean>;
736
+ }, "strip", z.ZodTypeAny, {
737
+ kind: "room";
738
+ exclude_self?: boolean | undefined;
739
+ exclude?: string[] | undefined;
740
+ include_bots?: boolean | undefined;
741
+ }, {
742
+ kind: "room";
743
+ exclude_self?: boolean | undefined;
744
+ exclude?: string[] | undefined;
745
+ include_bots?: boolean | undefined;
746
+ }>, z.ZodObject<{
747
+ /** 타이핑할 때마다 서버에 묻는다 — 답은 `org.corp.ui.action.result` 의 `kind: "options"`. */
748
+ kind: z.ZodLiteral<"query">;
749
+ /**
750
+ * 질의를 받을 액션. 클라는 `action_type: "query"` 로 `{ q, name }` 을 실어 보낸다.
751
+ * 🔴 사람이 누른 게 아니므로 앱은 **부작용 없이** `ctx.result({ kind: "options", name, options })`
752
+ * 로만 답해야 한다(같은 핸들러가 제출도 처리한다면 `action_type` 으로 갈라야 한다).
753
+ */
754
+ action_id: z.ZodString;
755
+ /** 몇 글자부터 묻나(기본 1). 한 글자에 전체 스캔이 도는 백엔드라면 올린다. */
756
+ min_chars: z.ZodOptional<z.ZodNumber>;
757
+ /** 타이핑이 멎고 몇 ms 뒤에 묻나(기본 300). */
758
+ debounce_ms: z.ZodOptional<z.ZodNumber>;
759
+ }, "strip", z.ZodTypeAny, {
760
+ kind: "query";
761
+ action_id: string;
762
+ min_chars?: number | undefined;
763
+ debounce_ms?: number | undefined;
764
+ }, {
765
+ kind: "query";
766
+ action_id: string;
767
+ min_chars?: number | undefined;
768
+ debounce_ms?: number | undefined;
769
+ }>]>>;
770
+ /**
771
+ * 표현 힌트 (0.9.0) — **능력이 아니라 룩이다.** 생략하면 렌더러가 후보 수·`multi`·`source` 로 고른다.
772
+ * · `list`/`segmented` — `radio` 의 같은 이름 표현과 **같은 뜻**(펼친 목록 / 한 줄 세그먼트).
773
+ * `multi` 와 같이 쓰면 그릴 수 있는 컨트롤이 없어 칩 콤보박스로 떨어진다.
774
+ * · `dropdown` — 트리거 + 떠 있는 목록(콤보박스). 네이티브 `<select>` 가 아니다.
775
+ * · `chips` — 고른 것이 트리거 안에서 칩으로 선다(`multi` 의 기본 표현).
776
+ */
777
+ style: z.ZodOptional<z.ZodEnum<["list", "segmented", "dropdown", "chips"]>>;
778
+ /**
779
+ * 목록 안 검색창 (0.9.0). 생략하면 렌더러가 켠다 — 후보가 8 개를 넘거나, 공급원이 방/질의일 때.
780
+ * 🔴 이건 "검색하기 **버튼**"이 아니다. 타이핑이 곧 필터이고, 왕복은 `source: query` 일 때만 돈다.
781
+ */
782
+ searchable: z.ZodOptional<z.ZodBoolean>;
627
783
  /** 고르지 않으면 제출을 잠근다 (0.7.0). 🔴 UX 다, 진실은 서버. */
628
784
  required: z.ZodOptional<z.ZodBoolean>;
629
785
  /**
@@ -648,6 +804,7 @@ export declare const SelectBlockSchema: z.ZodObject<{
648
804
  };
649
805
  url?: string | undefined;
650
806
  } | undefined;
807
+ hint?: string | undefined;
651
808
  }[];
652
809
  type: "select";
653
810
  name: string;
@@ -658,7 +815,20 @@ export declare const SelectBlockSchema: z.ZodObject<{
658
815
  min?: number | undefined;
659
816
  max?: number | undefined;
660
817
  error?: string | undefined;
818
+ style?: "segmented" | "list" | "dropdown" | "chips" | undefined;
661
819
  multi?: boolean | undefined;
820
+ source?: {
821
+ kind: "room";
822
+ exclude_self?: boolean | undefined;
823
+ exclude?: string[] | undefined;
824
+ include_bots?: boolean | undefined;
825
+ } | {
826
+ kind: "query";
827
+ action_id: string;
828
+ min_chars?: number | undefined;
829
+ debounce_ms?: number | undefined;
830
+ } | undefined;
831
+ searchable?: boolean | undefined;
662
832
  }, {
663
833
  options: {
664
834
  value: string;
@@ -672,6 +842,7 @@ export declare const SelectBlockSchema: z.ZodObject<{
672
842
  };
673
843
  url?: string | undefined;
674
844
  } | undefined;
845
+ hint?: string | undefined;
675
846
  }[];
676
847
  type: "select";
677
848
  name: string;
@@ -682,8 +853,24 @@ export declare const SelectBlockSchema: z.ZodObject<{
682
853
  min?: number | undefined;
683
854
  max?: number | undefined;
684
855
  error?: string | undefined;
856
+ style?: "segmented" | "list" | "dropdown" | "chips" | undefined;
685
857
  multi?: boolean | undefined;
858
+ source?: {
859
+ kind: "room";
860
+ exclude_self?: boolean | undefined;
861
+ exclude?: string[] | undefined;
862
+ include_bots?: boolean | undefined;
863
+ } | {
864
+ kind: "query";
865
+ action_id: string;
866
+ min_chars?: number | undefined;
867
+ debounce_ms?: number | undefined;
868
+ } | undefined;
869
+ searchable?: boolean | undefined;
686
870
  }>;
871
+ export type SelectBlock = z.infer<typeof SelectBlockSchema>;
872
+ /** 후보 한 줄 — `select.options[]` 와 `action.result` 의 `options[]` 가 같은 모양을 쓴다. */
873
+ export type SelectOption = SelectBlock["options"][number];
687
874
  export declare const CheckboxBlockSchema: z.ZodObject<{
688
875
  type: z.ZodLiteral<"checkbox">;
689
876
  name: z.ZodString;
@@ -803,6 +990,16 @@ export declare const ButtonBlockSchema: z.ZodObject<{
803
990
  * "눌러 봐야 안다"를 없애는 것이 요점이다. 🔴 UX 다, 진실은 서버.
804
991
  */
805
992
  disabled_reason: z.ZodOptional<z.ZodString>;
993
+ /**
994
+ * **중요도**(0.9.0) — 배치가 아니라 의도다. `"secondary"` 는 "이건 부차적이다"라는 말이고,
995
+ * 액션 줄이 좁아 한 줄에 못 들어갈 때 렌더러가 **먼저 ⋯ 메뉴로 접는** 대상이 된다.
996
+ *
997
+ * 🔴 **`style` 과 다른 축이다.** `style` 은 *생김새*(기본/강조/위험)이고 이것은 *중요도*다 —
998
+ * `style: "danger"` 인 "보고 취소"가 부차적일 수 있다(위험하지만 주 동작은 아니다). 둘을 한
999
+ * 축으로 묶으면 그 카드를 표현할 수 없다.
1000
+ * ⚠️ 생략하면 지금과 **완전히 같다**(안 접힌다). 접기는 `"secondary"` 를 선언한 것에만 일어난다.
1001
+ */
1002
+ priority: z.ZodOptional<z.ZodEnum<["primary", "secondary"]>>;
806
1003
  }, "strip", z.ZodTypeAny, {
807
1004
  type: "button";
808
1005
  text: string;
@@ -819,6 +1016,7 @@ export declare const ButtonBlockSchema: z.ZodObject<{
819
1016
  hidden_for?: string[] | undefined;
820
1017
  visible_for?: string[] | undefined;
821
1018
  disabled_reason?: string | undefined;
1019
+ priority?: "primary" | "secondary" | undefined;
822
1020
  }, {
823
1021
  type: "button";
824
1022
  text: string;
@@ -835,6 +1033,7 @@ export declare const ButtonBlockSchema: z.ZodObject<{
835
1033
  hidden_for?: string[] | undefined;
836
1034
  visible_for?: string[] | undefined;
837
1035
  disabled_reason?: string | undefined;
1036
+ priority?: "primary" | "secondary" | undefined;
838
1037
  }>;
839
1038
  export type ButtonBlock = z.infer<typeof ButtonBlockSchema>;
840
1039
  /**
@@ -849,185 +1048,24 @@ export declare const LinkButtonBlockSchema: z.ZodObject<{
849
1048
  style: z.ZodOptional<z.ZodEnum<["default", "primary", "danger"]>>;
850
1049
  /** 새 탭으로 열기(기본 true). */
851
1050
  external: z.ZodOptional<z.ZodBoolean>;
1051
+ /** 중요도 (0.9.0) — `ButtonBlockSchema.priority` 와 같은 뜻. 좁으면 ⋯ 로 접힌다. */
1052
+ priority: z.ZodOptional<z.ZodEnum<["primary", "secondary"]>>;
852
1053
  }, "strip", z.ZodTypeAny, {
853
1054
  type: "linkButton";
854
1055
  url: string;
855
1056
  text: string;
856
1057
  style?: "danger" | "default" | "primary" | undefined;
1058
+ priority?: "primary" | "secondary" | undefined;
857
1059
  external?: boolean | undefined;
858
1060
  }, {
859
1061
  type: "linkButton";
860
1062
  url: string;
861
1063
  text: string;
862
1064
  style?: "danger" | "default" | "primary" | undefined;
1065
+ priority?: "primary" | "secondary" | undefined;
863
1066
  external?: boolean | undefined;
864
1067
  }>;
865
1068
  export type LinkButtonBlock = z.infer<typeof LinkButtonBlockSchema>;
866
- /** 버튼 한 줄 묶음 — 액션 버튼(button)과 링크 버튼(linkButton)을 섞어 배치 가능. */
867
- export declare const ActionsBlockSchema: z.ZodObject<{
868
- type: z.ZodLiteral<"actions">;
869
- elements: z.ZodArray<z.ZodUnion<[z.ZodObject<{
870
- type: z.ZodLiteral<"button">;
871
- /** 어떤 액션인지 식별. 클릭 시 org.corp.ui.action.action_id 로 회신됨. */
872
- action_id: z.ZodString;
873
- text: z.ZodString;
874
- style: z.ZodOptional<z.ZodEnum<["default", "primary", "danger"]>>;
875
- /** 버튼 고유 페이로드 (폼 값과 별개로 함께 전송) */
876
- value: z.ZodOptional<z.ZodString>;
877
- confirm: z.ZodOptional<z.ZodObject<{
878
- title: z.ZodString;
879
- text: z.ZodString;
880
- ok: z.ZodOptional<z.ZodString>;
881
- cancel: z.ZodOptional<z.ZodString>;
882
- }, "strip", z.ZodTypeAny, {
883
- title: string;
884
- text: string;
885
- ok?: string | undefined;
886
- cancel?: string | undefined;
887
- }, {
888
- title: string;
889
- text: string;
890
- ok?: string | undefined;
891
- cancel?: string | undefined;
892
- }>>;
893
- disabled: z.ZodOptional<z.ZodBoolean>;
894
- /**
895
- * 이 MXID 들에게는 버튼을 **감춘다**(뷰어별 어포던스).
896
- *
897
- * 왜 필요한가: 카드 한 장은 방 전체가 같이 본다. 그런데 "이 사람만 절대 못 누르는 버튼"이 있다 —
898
- * Forgejo 는 **자기 PR 자기 승인**을 422 로 거절한다(`approve your own pull is not allowed`).
899
- * 그래서 작성자에게 Approve 를 보여 주면 눌러도 실패 카드만 쌓인다. 카드 전체에서 버튼을 빼면
900
- * 남들이 승인을 못 하므로, 판정은 **보는 사람별**이어야 한다.
901
- *
902
- * 🔴 **권한이 아니다.** 진짜 게이트는 언제나 서버다(disabled/confirm 과 같은 자세) — 이건 없는
903
- * 어포던스를 안 보여 주기 위한 것뿐이다. 그래서 이 키를 모르는 옛 클라이언트가 버튼을 그대로
904
- * 보여 줘도 안전하다(누르면 서버가 사람이 읽을 이유와 함께 거절한다).
905
- */
906
- hidden_for: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
907
- /**
908
- * `hidden_for` 의 **짝**(0.7.0) — 이 MXID 들에게만 버튼을 보인다(화이트리스트).
909
- *
910
- * 왜 둘 다 있나: 두 축은 아는 것이 다르다. `hidden_for` 는 "이 사람은 절대 못 누른다"를 아는 경우고
911
- * (자기 PR 자기 승인), `visible_for` 는 "이 사람만 누를 수 있다"를 아는 경우다(현재 수신자). 후자를
912
- * `hidden_for` 로 쓰려면 방 멤버 전원을 열거해야 하고, 그 목록은 카드를 만든 **순간**에 굳는다 —
913
- * 나중에 들어온 사람에게 버튼이 그냥 보인다.
914
- *
915
- * 🔴 **둘 다 있으면 `hidden_for` 가 이긴다.** "못 누른다"가 "누를 수 있다"보다 강한 진술이라서다
916
- * (겹치는 경우는 보통 작성자의 실수이고, 그때 안전한 쪽은 감추는 쪽이다).
917
- * 🔴 **권한이 아니다** — `hidden_for` 와 똑같이 UX 고, 진짜 게이트는 언제나 서버다.
918
- * 이 키를 모르는 옛 클라는 strip 하고 **전원에게** 버튼을 보인다 → 누르면 서버가 거절한다.
919
- */
920
- visible_for: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
921
- /**
922
- * 버튼이 잠기거나 감춰진 **이유 한 줄**(0.7.0) — 사람이 읽을 문장(작성자 소유).
923
- * `disabled` 면 버튼 옆 보조 텍스트로, `visible_for` 로 감춰졌으면 버튼 자리에 이 줄만 남는다.
924
- * "눌러 봐야 안다"를 없애는 것이 요점이다. 🔴 UX 다, 진실은 서버.
925
- */
926
- disabled_reason: z.ZodOptional<z.ZodString>;
927
- }, "strip", z.ZodTypeAny, {
928
- type: "button";
929
- text: string;
930
- action_id: string;
931
- value?: string | undefined;
932
- style?: "danger" | "default" | "primary" | undefined;
933
- confirm?: {
934
- title: string;
935
- text: string;
936
- ok?: string | undefined;
937
- cancel?: string | undefined;
938
- } | undefined;
939
- disabled?: boolean | undefined;
940
- hidden_for?: string[] | undefined;
941
- visible_for?: string[] | undefined;
942
- disabled_reason?: string | undefined;
943
- }, {
944
- type: "button";
945
- text: string;
946
- action_id: string;
947
- value?: string | undefined;
948
- style?: "danger" | "default" | "primary" | undefined;
949
- confirm?: {
950
- title: string;
951
- text: string;
952
- ok?: string | undefined;
953
- cancel?: string | undefined;
954
- } | undefined;
955
- disabled?: boolean | undefined;
956
- hidden_for?: string[] | undefined;
957
- visible_for?: string[] | undefined;
958
- disabled_reason?: string | undefined;
959
- }>, z.ZodObject<{
960
- type: z.ZodLiteral<"linkButton">;
961
- text: z.ZodString;
962
- /** 이동할 https URL. 클라이언트가 출처를 검증(아니면 비활성 표시). */
963
- url: z.ZodString;
964
- style: z.ZodOptional<z.ZodEnum<["default", "primary", "danger"]>>;
965
- /** 새 탭으로 열기(기본 true). */
966
- external: z.ZodOptional<z.ZodBoolean>;
967
- }, "strip", z.ZodTypeAny, {
968
- type: "linkButton";
969
- url: string;
970
- text: string;
971
- style?: "danger" | "default" | "primary" | undefined;
972
- external?: boolean | undefined;
973
- }, {
974
- type: "linkButton";
975
- url: string;
976
- text: string;
977
- style?: "danger" | "default" | "primary" | undefined;
978
- external?: boolean | undefined;
979
- }>]>, "many">;
980
- }, "strip", z.ZodTypeAny, {
981
- type: "actions";
982
- elements: ({
983
- type: "button";
984
- text: string;
985
- action_id: string;
986
- value?: string | undefined;
987
- style?: "danger" | "default" | "primary" | undefined;
988
- confirm?: {
989
- title: string;
990
- text: string;
991
- ok?: string | undefined;
992
- cancel?: string | undefined;
993
- } | undefined;
994
- disabled?: boolean | undefined;
995
- hidden_for?: string[] | undefined;
996
- visible_for?: string[] | undefined;
997
- disabled_reason?: string | undefined;
998
- } | {
999
- type: "linkButton";
1000
- url: string;
1001
- text: string;
1002
- style?: "danger" | "default" | "primary" | undefined;
1003
- external?: boolean | undefined;
1004
- })[];
1005
- }, {
1006
- type: "actions";
1007
- elements: ({
1008
- type: "button";
1009
- text: string;
1010
- action_id: string;
1011
- value?: string | undefined;
1012
- style?: "danger" | "default" | "primary" | undefined;
1013
- confirm?: {
1014
- title: string;
1015
- text: string;
1016
- ok?: string | undefined;
1017
- cancel?: string | undefined;
1018
- } | undefined;
1019
- disabled?: boolean | undefined;
1020
- hidden_for?: string[] | undefined;
1021
- visible_for?: string[] | undefined;
1022
- disabled_reason?: string | undefined;
1023
- } | {
1024
- type: "linkButton";
1025
- url: string;
1026
- text: string;
1027
- style?: "danger" | "default" | "primary" | undefined;
1028
- external?: boolean | undefined;
1029
- })[];
1030
- }>;
1031
1069
  /**
1032
1070
  * 오버플로 메뉴 — "⋯" 트리거를 누르면 액션 항목 목록이 팝오버로 열린다(공간 절약형 액션 묶음).
1033
1071
  * 각 항목은 button 과 동일하게 action_id 로 회신하고 confirm(파괴적 액션 확인)도 지원.
@@ -1137,6 +1175,38 @@ export declare const OverflowBlockSchema: z.ZodObject<{
1137
1175
  label?: string | undefined;
1138
1176
  }>;
1139
1177
  export type OverflowBlock = z.infer<typeof OverflowBlockSchema>;
1178
+ /**
1179
+ * **액션 줄의 원소**(0.9.0 부터 셋) — 버튼 · 링크 버튼 · ⋯ 메뉴.
1180
+ *
1181
+ * 🔴 `overflow` 가 여기 들어온 이유는 배치다(감사 문서 D). 최상위 블록으로만 둘 수 있던 시절엔
1182
+ * 세로 flex 인 `.cob-blocks` 안에서 **제 줄을 통째로 먹었다** — 버튼 넷 아래에 ⋯ 하나가 두 번째
1183
+ * 줄에 혼자 서는 모양이다. 액션 줄 안으로 들어오면 그 줄의 끝에 선다.
1184
+ *
1185
+ * ⚠️ **옛 클라에는 이 원소가 안 보인다.** 유니온이 닫혀 있어 모르는 원소 하나가 배열 전체를
1186
+ * 실패시키고 → `dropUnknownBlocks` 가 그 **actions 블록을 통째로** 떨군다(0.9.0 의
1187
+ * `dropUnknownBlocks` 는 원소 단위로 거르지만 그건 *새* 클라 이야기다). 그래서 빌더
1188
+ * (`card.actions`)가 전환기 동안 **최상위 `overflow` 사본**을 같이 낸다 — `card.activity` 의
1189
+ * `legacy_for` 와 같은 규약이고, 새 렌더러는 사본을 알아보고 건너뛴다.
1190
+ */
1191
+ /**
1192
+ * 🔴 **타입을 손으로 적고 스키마에 주석을 단다** — `z.infer` 로 두면 TS 가 이 유니온을 통째로
1193
+ * 펼치는데, `overflow` 가 들어오면서 그 펼친 타입이 `surfaces.ts` 의 `AppSurfaceContentSchema`
1194
+ * (패널 → 서피스 바디 → 카드 → 블록 → 액션)까지 타고 올라가 **직렬화 한도를 넘는다**(TS7056).
1195
+ * 주석 한 줄이 그 자리에서 추론을 끊는다. 값의 모양은 그대로다.
1196
+ */
1197
+ export type ActionElement = ButtonBlock | LinkButtonBlock | OverflowBlock;
1198
+ export declare const ActionElementSchema: z.ZodType<ActionElement>;
1199
+ /** 버튼 한 줄 묶음 — 액션 버튼(button)·링크 버튼(linkButton)·⋯ 메뉴(overflow)를 섞어 배치 가능. */
1200
+ export declare const ActionsBlockSchema: z.ZodObject<{
1201
+ type: z.ZodLiteral<"actions">;
1202
+ elements: z.ZodArray<z.ZodType<ActionElement, z.ZodTypeDef, ActionElement>, "many">;
1203
+ }, "strip", z.ZodTypeAny, {
1204
+ type: "actions";
1205
+ elements: ActionElement[];
1206
+ }, {
1207
+ type: "actions";
1208
+ elements: ActionElement[];
1209
+ }>;
1140
1210
  /**
1141
1211
  * 진행률 바 (0~100). 에이전트가 m.replace 편집으로 갱신해 "스트리밍" 진행 표시 가능.
1142
1212
  *
@@ -1742,6 +1812,15 @@ export declare const CollapsibleBlockSchema: z.ZodObject<{
1742
1812
  * 전환기가 끝나 클라 배포가 충분히 퍼지면 빌더의 `legacy` 기본값을 false 로 바꾼다(이 시리즈 밖).
1743
1813
  */
1744
1814
  legacy_for: z.ZodOptional<z.ZodEnum<["activity"]>>;
1815
+ /**
1816
+ * **접힌 채로도 보이는 한 줄**(0.9.0) — 제목 오른쪽에 흐리게 선다. 펼치면 숨는다(본문이 답이다).
1817
+ *
1818
+ * 왜 필요한가(감사 문서 D): 접기는 "카드 높이를 안 먹는 상세"인데, 지금은 접힌 상태에서 **정보가
1819
+ * 0** 이라 사용자가 펼쳐 봐야 안에 뭐가 있는지 안다. 마지막 한 줄만 보여 주면 대개 펼칠 필요가 없다
1820
+ * ("마지막: 희태 박에게 전달 · 6:12").
1821
+ * ⚠️ 본문의 요약이지 본문의 **대체**가 아니다 — 여기만 읽고 끝나도 되는 내용이면 접지 말 것.
1822
+ */
1823
+ summary: z.ZodOptional<z.ZodString>;
1745
1824
  /**
1746
1825
  * 펼치면 보이는 중첩 블록(재귀). 런타임은 z.lazy 로 BlockSchema 를 지연 참조해 재귀 검증하지만,
1747
1826
  * 정적 타입은 z.ZodTypeAny 로 끊는다 — Block 이 z.infer 기반이라 재귀 타입 별칭이 conditional type
@@ -1755,6 +1834,7 @@ export declare const CollapsibleBlockSchema: z.ZodObject<{
1755
1834
  tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
1756
1835
  open?: boolean | undefined;
1757
1836
  legacy_for?: "activity" | undefined;
1837
+ summary?: string | undefined;
1758
1838
  }, {
1759
1839
  type: "collapsible";
1760
1840
  title: string;
@@ -1762,6 +1842,7 @@ export declare const CollapsibleBlockSchema: z.ZodObject<{
1762
1842
  tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
1763
1843
  open?: boolean | undefined;
1764
1844
  legacy_for?: "activity" | undefined;
1845
+ summary?: string | undefined;
1765
1846
  }>;
1766
1847
  export type CollapsibleBlock = {
1767
1848
  type: "collapsible";
@@ -1769,6 +1850,7 @@ export type CollapsibleBlock = {
1769
1850
  open?: boolean;
1770
1851
  tone?: Tone;
1771
1852
  legacy_for?: "activity";
1853
+ summary?: string;
1772
1854
  blocks: Block[];
1773
1855
  };
1774
1856
  /**
@@ -2099,6 +2181,16 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
2099
2181
  };
2100
2182
  url?: string | undefined;
2101
2183
  }>]>>;
2184
+ /**
2185
+ * **이 항목은 문단이다**(0.9.0) — 값이 아니라 본문. 전체폭으로 서고 값 서체(600)를 풀며
2186
+ * 인라인 마크다운을 그린다.
2187
+ *
2188
+ * 왜 필요한가(감사 문서 D): "막힌 일: ㅁㄴㄹ…" 같은 자유 서술이 지금은 굵은 값 서체로 서서
2189
+ * 숫자·상태와 같은 무게로 읽힌다. 작성자가 `short` 로 열 수를 강제하던 것과 같은 자리 —
2190
+ * 작성자는 "이건 문단이다"만 말하고 폭·서체는 렌더러가 정한다.
2191
+ * ⚠️ `short` 와 같이 주면 `long` 이 이긴다(반폭 문단은 없다).
2192
+ */
2193
+ long: z.ZodOptional<z.ZodBoolean>;
2102
2194
  }, "strip", z.ZodTypeAny, {
2103
2195
  value: string;
2104
2196
  label: string;
@@ -2116,6 +2208,7 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
2116
2208
  };
2117
2209
  url?: string | undefined;
2118
2210
  } | undefined;
2211
+ long?: boolean | undefined;
2119
2212
  }, {
2120
2213
  value: string;
2121
2214
  label: string;
@@ -2133,7 +2226,17 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
2133
2226
  };
2134
2227
  url?: string | undefined;
2135
2228
  } | undefined;
2229
+ long?: boolean | undefined;
2136
2230
  }>, "many">;
2231
+ /**
2232
+ * 열 수 **명시 오버라이드**(0.9.0). 생략이 기본이고, 기본은 폭이 정하는 auto-fit 이다
2233
+ * (그리고 `short` 넷이면 2×2 로 묶인다 — 0.7.0 에서 이미 들어간 규칙).
2234
+ *
2235
+ * 🔴 **기본을 되돌리지 않는다.** 이 키는 auto-fit 이 틀리는 드문 경우(라벨이 길어 3열이 찢어지는
2236
+ * 표 같은 fields)를 위한 탈출구다 — 늘 주면 좁은 화면에서 열이 안 줄어 값이 짜부라진다.
2237
+ * `"auto"` 는 명시적으로 기본을 고르는 값이다(작성자가 "여긴 렌더러에 맡긴다"를 적을 수 있게).
2238
+ */
2239
+ columns: z.ZodOptional<z.ZodUnion<[z.ZodLiteral<2>, z.ZodLiteral<3>, z.ZodLiteral<"auto">]>>;
2137
2240
  }, "strip", z.ZodTypeAny, {
2138
2241
  type: "fields";
2139
2242
  items: {
@@ -2153,7 +2256,9 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
2153
2256
  };
2154
2257
  url?: string | undefined;
2155
2258
  } | undefined;
2259
+ long?: boolean | undefined;
2156
2260
  }[];
2261
+ columns?: 2 | 3 | "auto" | undefined;
2157
2262
  }, {
2158
2263
  type: "fields";
2159
2264
  items: {
@@ -2173,7 +2278,9 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
2173
2278
  };
2174
2279
  url?: string | undefined;
2175
2280
  } | undefined;
2281
+ long?: boolean | undefined;
2176
2282
  }[];
2283
+ columns?: 2 | 3 | "auto" | undefined;
2177
2284
  }>, z.ZodObject<{
2178
2285
  type: z.ZodLiteral<"image">;
2179
2286
  /** https URL 또는 mxc:// (둘 중 하나 권장). 클라이언트가 출처를 검증한다. */
@@ -2945,6 +3052,15 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
2945
3052
  * 전환기가 끝나 클라 배포가 충분히 퍼지면 빌더의 `legacy` 기본값을 false 로 바꾼다(이 시리즈 밖).
2946
3053
  */
2947
3054
  legacy_for: z.ZodOptional<z.ZodEnum<["activity"]>>;
3055
+ /**
3056
+ * **접힌 채로도 보이는 한 줄**(0.9.0) — 제목 오른쪽에 흐리게 선다. 펼치면 숨는다(본문이 답이다).
3057
+ *
3058
+ * 왜 필요한가(감사 문서 D): 접기는 "카드 높이를 안 먹는 상세"인데, 지금은 접힌 상태에서 **정보가
3059
+ * 0** 이라 사용자가 펼쳐 봐야 안에 뭐가 있는지 안다. 마지막 한 줄만 보여 주면 대개 펼칠 필요가 없다
3060
+ * ("마지막: 희태 박에게 전달 · 6:12").
3061
+ * ⚠️ 본문의 요약이지 본문의 **대체**가 아니다 — 여기만 읽고 끝나도 되는 내용이면 접지 말 것.
3062
+ */
3063
+ summary: z.ZodOptional<z.ZodString>;
2948
3064
  /**
2949
3065
  * 펼치면 보이는 중첩 블록(재귀). 런타임은 z.lazy 로 BlockSchema 를 지연 참조해 재귀 검증하지만,
2950
3066
  * 정적 타입은 z.ZodTypeAny 로 끊는다 — Block 이 z.infer 기반이라 재귀 타입 별칭이 conditional type
@@ -2958,6 +3074,7 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
2958
3074
  tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
2959
3075
  open?: boolean | undefined;
2960
3076
  legacy_for?: "activity" | undefined;
3077
+ summary?: string | undefined;
2961
3078
  }, {
2962
3079
  type: "collapsible";
2963
3080
  title: string;
@@ -2965,6 +3082,7 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
2965
3082
  tone?: "neutral" | "success" | "warning" | "danger" | "info" | undefined;
2966
3083
  open?: boolean | undefined;
2967
3084
  legacy_for?: "activity" | undefined;
3085
+ summary?: string | undefined;
2968
3086
  }>, z.ZodObject<{
2969
3087
  type: z.ZodLiteral<"widget">;
2970
3088
  url: z.ZodString;
@@ -3182,11 +3300,13 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
3182
3300
  placeholder: z.ZodOptional<z.ZodString>;
3183
3301
  /**
3184
3302
  * 후보 목록. `ref`(0.8.0)를 주면 렌더러가 행을 칩(아바타·이름·MXID)으로 그린다 —
3185
- * 🔴 `label` 은 평문 사본으로 남긴다(RefSchema 머리말). 그리는 쪽은 P5(선택 모델)가 맡는다.
3303
+ * 🔴 `label` 은 평문 사본으로 남긴다(RefSchema 머리말).
3304
+ * `hint`(0.9.0)는 라벨 아래 한 줄 보조 설명 — `radio` 의 같은 이름 키와 같은 뜻이다.
3186
3305
  */
3187
3306
  options: z.ZodArray<z.ZodObject<{
3188
3307
  value: z.ZodString;
3189
3308
  label: z.ZodString;
3309
+ hint: z.ZodOptional<z.ZodString>;
3190
3310
  ref: z.ZodOptional<z.ZodUnion<[z.ZodObject<{
3191
3311
  /** Matrix 사용자 id — `@local:server` 형태. 해석(이름·아바타)은 호스트가 주입한다(PeopleProvider). */
3192
3312
  user: z.ZodString;
@@ -3233,6 +3353,7 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
3233
3353
  };
3234
3354
  url?: string | undefined;
3235
3355
  } | undefined;
3356
+ hint?: string | undefined;
3236
3357
  }, {
3237
3358
  value: string;
3238
3359
  label: string;
@@ -3245,9 +3366,67 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
3245
3366
  };
3246
3367
  url?: string | undefined;
3247
3368
  } | undefined;
3369
+ hint?: string | undefined;
3248
3370
  }>, "many">;
3249
3371
  value: z.ZodOptional<z.ZodString>;
3250
3372
  multi: z.ZodOptional<z.ZodBoolean>;
3373
+ /** 후보가 어디서 오나 (0.9.0). 생략 = `options` 배열. 위 `SelectSourceSchema` 머리말 참조. */
3374
+ source: z.ZodOptional<z.ZodUnion<[z.ZodObject<{
3375
+ /** 이 방의 멤버가 후보다. 값은 MXID 배열이고, 이름·아바타는 클라가 방 상태로 해석한다. */
3376
+ kind: z.ZodLiteral<"room">;
3377
+ /** 보는 사람 자신을 후보에서 뺀다(기본 false). "받을 사람"처럼 나를 고를 일이 없는 자리. */
3378
+ exclude_self: z.ZodOptional<z.ZodBoolean>;
3379
+ /** 후보에서 뺄 MXID 목록 — 이미 담당인 사람, 퇴사 처리 중인 계정 등. */
3380
+ exclude: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
3381
+ /** 봇·에이전트 계정도 후보에 넣는다(기본 false — 사람을 고르는 자리가 대부분이다). */
3382
+ include_bots: z.ZodOptional<z.ZodBoolean>;
3383
+ }, "strip", z.ZodTypeAny, {
3384
+ kind: "room";
3385
+ exclude_self?: boolean | undefined;
3386
+ exclude?: string[] | undefined;
3387
+ include_bots?: boolean | undefined;
3388
+ }, {
3389
+ kind: "room";
3390
+ exclude_self?: boolean | undefined;
3391
+ exclude?: string[] | undefined;
3392
+ include_bots?: boolean | undefined;
3393
+ }>, z.ZodObject<{
3394
+ /** 타이핑할 때마다 서버에 묻는다 — 답은 `org.corp.ui.action.result` 의 `kind: "options"`. */
3395
+ kind: z.ZodLiteral<"query">;
3396
+ /**
3397
+ * 질의를 받을 액션. 클라는 `action_type: "query"` 로 `{ q, name }` 을 실어 보낸다.
3398
+ * 🔴 사람이 누른 게 아니므로 앱은 **부작용 없이** `ctx.result({ kind: "options", name, options })`
3399
+ * 로만 답해야 한다(같은 핸들러가 제출도 처리한다면 `action_type` 으로 갈라야 한다).
3400
+ */
3401
+ action_id: z.ZodString;
3402
+ /** 몇 글자부터 묻나(기본 1). 한 글자에 전체 스캔이 도는 백엔드라면 올린다. */
3403
+ min_chars: z.ZodOptional<z.ZodNumber>;
3404
+ /** 타이핑이 멎고 몇 ms 뒤에 묻나(기본 300). */
3405
+ debounce_ms: z.ZodOptional<z.ZodNumber>;
3406
+ }, "strip", z.ZodTypeAny, {
3407
+ kind: "query";
3408
+ action_id: string;
3409
+ min_chars?: number | undefined;
3410
+ debounce_ms?: number | undefined;
3411
+ }, {
3412
+ kind: "query";
3413
+ action_id: string;
3414
+ min_chars?: number | undefined;
3415
+ debounce_ms?: number | undefined;
3416
+ }>]>>;
3417
+ /**
3418
+ * 표현 힌트 (0.9.0) — **능력이 아니라 룩이다.** 생략하면 렌더러가 후보 수·`multi`·`source` 로 고른다.
3419
+ * · `list`/`segmented` — `radio` 의 같은 이름 표현과 **같은 뜻**(펼친 목록 / 한 줄 세그먼트).
3420
+ * `multi` 와 같이 쓰면 그릴 수 있는 컨트롤이 없어 칩 콤보박스로 떨어진다.
3421
+ * · `dropdown` — 트리거 + 떠 있는 목록(콤보박스). 네이티브 `<select>` 가 아니다.
3422
+ * · `chips` — 고른 것이 트리거 안에서 칩으로 선다(`multi` 의 기본 표현).
3423
+ */
3424
+ style: z.ZodOptional<z.ZodEnum<["list", "segmented", "dropdown", "chips"]>>;
3425
+ /**
3426
+ * 목록 안 검색창 (0.9.0). 생략하면 렌더러가 켠다 — 후보가 8 개를 넘거나, 공급원이 방/질의일 때.
3427
+ * 🔴 이건 "검색하기 **버튼**"이 아니다. 타이핑이 곧 필터이고, 왕복은 `source: query` 일 때만 돈다.
3428
+ */
3429
+ searchable: z.ZodOptional<z.ZodBoolean>;
3251
3430
  /** 고르지 않으면 제출을 잠근다 (0.7.0). 🔴 UX 다, 진실은 서버. */
3252
3431
  required: z.ZodOptional<z.ZodBoolean>;
3253
3432
  /**
@@ -3272,6 +3451,7 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
3272
3451
  };
3273
3452
  url?: string | undefined;
3274
3453
  } | undefined;
3454
+ hint?: string | undefined;
3275
3455
  }[];
3276
3456
  type: "select";
3277
3457
  name: string;
@@ -3282,7 +3462,20 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
3282
3462
  min?: number | undefined;
3283
3463
  max?: number | undefined;
3284
3464
  error?: string | undefined;
3465
+ style?: "segmented" | "list" | "dropdown" | "chips" | undefined;
3285
3466
  multi?: boolean | undefined;
3467
+ source?: {
3468
+ kind: "room";
3469
+ exclude_self?: boolean | undefined;
3470
+ exclude?: string[] | undefined;
3471
+ include_bots?: boolean | undefined;
3472
+ } | {
3473
+ kind: "query";
3474
+ action_id: string;
3475
+ min_chars?: number | undefined;
3476
+ debounce_ms?: number | undefined;
3477
+ } | undefined;
3478
+ searchable?: boolean | undefined;
3286
3479
  }, {
3287
3480
  options: {
3288
3481
  value: string;
@@ -3296,6 +3489,7 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
3296
3489
  };
3297
3490
  url?: string | undefined;
3298
3491
  } | undefined;
3492
+ hint?: string | undefined;
3299
3493
  }[];
3300
3494
  type: "select";
3301
3495
  name: string;
@@ -3306,7 +3500,20 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
3306
3500
  min?: number | undefined;
3307
3501
  max?: number | undefined;
3308
3502
  error?: string | undefined;
3503
+ style?: "segmented" | "list" | "dropdown" | "chips" | undefined;
3309
3504
  multi?: boolean | undefined;
3505
+ source?: {
3506
+ kind: "room";
3507
+ exclude_self?: boolean | undefined;
3508
+ exclude?: string[] | undefined;
3509
+ include_bots?: boolean | undefined;
3510
+ } | {
3511
+ kind: "query";
3512
+ action_id: string;
3513
+ min_chars?: number | undefined;
3514
+ debounce_ms?: number | undefined;
3515
+ } | undefined;
3516
+ searchable?: boolean | undefined;
3310
3517
  }>, z.ZodObject<{
3311
3518
  type: z.ZodLiteral<"checkbox">;
3312
3519
  name: z.ZodString;
@@ -3410,6 +3617,16 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
3410
3617
  * "눌러 봐야 안다"를 없애는 것이 요점이다. 🔴 UX 다, 진실은 서버.
3411
3618
  */
3412
3619
  disabled_reason: z.ZodOptional<z.ZodString>;
3620
+ /**
3621
+ * **중요도**(0.9.0) — 배치가 아니라 의도다. `"secondary"` 는 "이건 부차적이다"라는 말이고,
3622
+ * 액션 줄이 좁아 한 줄에 못 들어갈 때 렌더러가 **먼저 ⋯ 메뉴로 접는** 대상이 된다.
3623
+ *
3624
+ * 🔴 **`style` 과 다른 축이다.** `style` 은 *생김새*(기본/강조/위험)이고 이것은 *중요도*다 —
3625
+ * `style: "danger"` 인 "보고 취소"가 부차적일 수 있다(위험하지만 주 동작은 아니다). 둘을 한
3626
+ * 축으로 묶으면 그 카드를 표현할 수 없다.
3627
+ * ⚠️ 생략하면 지금과 **완전히 같다**(안 접힌다). 접기는 `"secondary"` 를 선언한 것에만 일어난다.
3628
+ */
3629
+ priority: z.ZodOptional<z.ZodEnum<["primary", "secondary"]>>;
3413
3630
  }, "strip", z.ZodTypeAny, {
3414
3631
  type: "button";
3415
3632
  text: string;
@@ -3426,6 +3643,7 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
3426
3643
  hidden_for?: string[] | undefined;
3427
3644
  visible_for?: string[] | undefined;
3428
3645
  disabled_reason?: string | undefined;
3646
+ priority?: "primary" | "secondary" | undefined;
3429
3647
  }, {
3430
3648
  type: "button";
3431
3649
  text: string;
@@ -3442,6 +3660,7 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
3442
3660
  hidden_for?: string[] | undefined;
3443
3661
  visible_for?: string[] | undefined;
3444
3662
  disabled_reason?: string | undefined;
3663
+ priority?: "primary" | "secondary" | undefined;
3445
3664
  }>, z.ZodObject<{
3446
3665
  type: z.ZodLiteral<"linkButton">;
3447
3666
  text: z.ZodString;
@@ -3450,181 +3669,31 @@ export declare const BlockSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
3450
3669
  style: z.ZodOptional<z.ZodEnum<["default", "primary", "danger"]>>;
3451
3670
  /** 새 탭으로 열기(기본 true). */
3452
3671
  external: z.ZodOptional<z.ZodBoolean>;
3672
+ /** 중요도 (0.9.0) — `ButtonBlockSchema.priority` 와 같은 뜻. 좁으면 ⋯ 로 접힌다. */
3673
+ priority: z.ZodOptional<z.ZodEnum<["primary", "secondary"]>>;
3453
3674
  }, "strip", z.ZodTypeAny, {
3454
3675
  type: "linkButton";
3455
3676
  url: string;
3456
3677
  text: string;
3457
3678
  style?: "danger" | "default" | "primary" | undefined;
3679
+ priority?: "primary" | "secondary" | undefined;
3458
3680
  external?: boolean | undefined;
3459
3681
  }, {
3460
3682
  type: "linkButton";
3461
3683
  url: string;
3462
3684
  text: string;
3463
3685
  style?: "danger" | "default" | "primary" | undefined;
3686
+ priority?: "primary" | "secondary" | undefined;
3464
3687
  external?: boolean | undefined;
3465
3688
  }>, z.ZodObject<{
3466
3689
  type: z.ZodLiteral<"actions">;
3467
- elements: z.ZodArray<z.ZodUnion<[z.ZodObject<{
3468
- type: z.ZodLiteral<"button">;
3469
- /** 어떤 액션인지 식별. 클릭 시 org.corp.ui.action.action_id 로 회신됨. */
3470
- action_id: z.ZodString;
3471
- text: z.ZodString;
3472
- style: z.ZodOptional<z.ZodEnum<["default", "primary", "danger"]>>;
3473
- /** 버튼 고유 페이로드 (폼 값과 별개로 함께 전송) */
3474
- value: z.ZodOptional<z.ZodString>;
3475
- confirm: z.ZodOptional<z.ZodObject<{
3476
- title: z.ZodString;
3477
- text: z.ZodString;
3478
- ok: z.ZodOptional<z.ZodString>;
3479
- cancel: z.ZodOptional<z.ZodString>;
3480
- }, "strip", z.ZodTypeAny, {
3481
- title: string;
3482
- text: string;
3483
- ok?: string | undefined;
3484
- cancel?: string | undefined;
3485
- }, {
3486
- title: string;
3487
- text: string;
3488
- ok?: string | undefined;
3489
- cancel?: string | undefined;
3490
- }>>;
3491
- disabled: z.ZodOptional<z.ZodBoolean>;
3492
- /**
3493
- * 이 MXID 들에게는 버튼을 **감춘다**(뷰어별 어포던스).
3494
- *
3495
- * 왜 필요한가: 카드 한 장은 방 전체가 같이 본다. 그런데 "이 사람만 절대 못 누르는 버튼"이 있다 —
3496
- * Forgejo 는 **자기 PR 자기 승인**을 422 로 거절한다(`approve your own pull is not allowed`).
3497
- * 그래서 작성자에게 Approve 를 보여 주면 눌러도 실패 카드만 쌓인다. 카드 전체에서 버튼을 빼면
3498
- * 남들이 승인을 못 하므로, 판정은 **보는 사람별**이어야 한다.
3499
- *
3500
- * 🔴 **권한이 아니다.** 진짜 게이트는 언제나 서버다(disabled/confirm 과 같은 자세) — 이건 없는
3501
- * 어포던스를 안 보여 주기 위한 것뿐이다. 그래서 이 키를 모르는 옛 클라이언트가 버튼을 그대로
3502
- * 보여 줘도 안전하다(누르면 서버가 사람이 읽을 이유와 함께 거절한다).
3503
- */
3504
- hidden_for: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
3505
- /**
3506
- * `hidden_for` 의 **짝**(0.7.0) — 이 MXID 들에게만 버튼을 보인다(화이트리스트).
3507
- *
3508
- * 왜 둘 다 있나: 두 축은 아는 것이 다르다. `hidden_for` 는 "이 사람은 절대 못 누른다"를 아는 경우고
3509
- * (자기 PR 자기 승인), `visible_for` 는 "이 사람만 누를 수 있다"를 아는 경우다(현재 수신자). 후자를
3510
- * `hidden_for` 로 쓰려면 방 멤버 전원을 열거해야 하고, 그 목록은 카드를 만든 **순간**에 굳는다 —
3511
- * 나중에 들어온 사람에게 버튼이 그냥 보인다.
3512
- *
3513
- * 🔴 **둘 다 있으면 `hidden_for` 가 이긴다.** "못 누른다"가 "누를 수 있다"보다 강한 진술이라서다
3514
- * (겹치는 경우는 보통 작성자의 실수이고, 그때 안전한 쪽은 감추는 쪽이다).
3515
- * 🔴 **권한이 아니다** — `hidden_for` 와 똑같이 UX 고, 진짜 게이트는 언제나 서버다.
3516
- * 이 키를 모르는 옛 클라는 strip 하고 **전원에게** 버튼을 보인다 → 누르면 서버가 거절한다.
3517
- */
3518
- visible_for: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
3519
- /**
3520
- * 버튼이 잠기거나 감춰진 **이유 한 줄**(0.7.0) — 사람이 읽을 문장(작성자 소유).
3521
- * `disabled` 면 버튼 옆 보조 텍스트로, `visible_for` 로 감춰졌으면 버튼 자리에 이 줄만 남는다.
3522
- * "눌러 봐야 안다"를 없애는 것이 요점이다. 🔴 UX 다, 진실은 서버.
3523
- */
3524
- disabled_reason: z.ZodOptional<z.ZodString>;
3525
- }, "strip", z.ZodTypeAny, {
3526
- type: "button";
3527
- text: string;
3528
- action_id: string;
3529
- value?: string | undefined;
3530
- style?: "danger" | "default" | "primary" | undefined;
3531
- confirm?: {
3532
- title: string;
3533
- text: string;
3534
- ok?: string | undefined;
3535
- cancel?: string | undefined;
3536
- } | undefined;
3537
- disabled?: boolean | undefined;
3538
- hidden_for?: string[] | undefined;
3539
- visible_for?: string[] | undefined;
3540
- disabled_reason?: string | undefined;
3541
- }, {
3542
- type: "button";
3543
- text: string;
3544
- action_id: string;
3545
- value?: string | undefined;
3546
- style?: "danger" | "default" | "primary" | undefined;
3547
- confirm?: {
3548
- title: string;
3549
- text: string;
3550
- ok?: string | undefined;
3551
- cancel?: string | undefined;
3552
- } | undefined;
3553
- disabled?: boolean | undefined;
3554
- hidden_for?: string[] | undefined;
3555
- visible_for?: string[] | undefined;
3556
- disabled_reason?: string | undefined;
3557
- }>, z.ZodObject<{
3558
- type: z.ZodLiteral<"linkButton">;
3559
- text: z.ZodString;
3560
- /** 이동할 https URL. 클라이언트가 출처를 검증(아니면 비활성 표시). */
3561
- url: z.ZodString;
3562
- style: z.ZodOptional<z.ZodEnum<["default", "primary", "danger"]>>;
3563
- /** 새 탭으로 열기(기본 true). */
3564
- external: z.ZodOptional<z.ZodBoolean>;
3565
- }, "strip", z.ZodTypeAny, {
3566
- type: "linkButton";
3567
- url: string;
3568
- text: string;
3569
- style?: "danger" | "default" | "primary" | undefined;
3570
- external?: boolean | undefined;
3571
- }, {
3572
- type: "linkButton";
3573
- url: string;
3574
- text: string;
3575
- style?: "danger" | "default" | "primary" | undefined;
3576
- external?: boolean | undefined;
3577
- }>]>, "many">;
3690
+ elements: z.ZodArray<z.ZodType<ActionElement, z.ZodTypeDef, ActionElement>, "many">;
3578
3691
  }, "strip", z.ZodTypeAny, {
3579
3692
  type: "actions";
3580
- elements: ({
3581
- type: "button";
3582
- text: string;
3583
- action_id: string;
3584
- value?: string | undefined;
3585
- style?: "danger" | "default" | "primary" | undefined;
3586
- confirm?: {
3587
- title: string;
3588
- text: string;
3589
- ok?: string | undefined;
3590
- cancel?: string | undefined;
3591
- } | undefined;
3592
- disabled?: boolean | undefined;
3593
- hidden_for?: string[] | undefined;
3594
- visible_for?: string[] | undefined;
3595
- disabled_reason?: string | undefined;
3596
- } | {
3597
- type: "linkButton";
3598
- url: string;
3599
- text: string;
3600
- style?: "danger" | "default" | "primary" | undefined;
3601
- external?: boolean | undefined;
3602
- })[];
3693
+ elements: ActionElement[];
3603
3694
  }, {
3604
3695
  type: "actions";
3605
- elements: ({
3606
- type: "button";
3607
- text: string;
3608
- action_id: string;
3609
- value?: string | undefined;
3610
- style?: "danger" | "default" | "primary" | undefined;
3611
- confirm?: {
3612
- title: string;
3613
- text: string;
3614
- ok?: string | undefined;
3615
- cancel?: string | undefined;
3616
- } | undefined;
3617
- disabled?: boolean | undefined;
3618
- hidden_for?: string[] | undefined;
3619
- visible_for?: string[] | undefined;
3620
- disabled_reason?: string | undefined;
3621
- } | {
3622
- type: "linkButton";
3623
- url: string;
3624
- text: string;
3625
- style?: "danger" | "default" | "primary" | undefined;
3626
- external?: boolean | undefined;
3627
- })[];
3696
+ elements: ActionElement[];
3628
3697
  }>, z.ZodObject<{
3629
3698
  type: z.ZodLiteral<"overflow">;
3630
3699
  /** 트리거 접근성 라벨(기본 "More actions"). */