@wipco/sdui-editor 0.16.0 → 0.17.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/index.d.ts +346 -8
- package/dist/index.js +1371 -710
- package/dist/styles.css +30 -0
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,87 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import React__default from 'react';
|
|
3
|
-
import {
|
|
3
|
+
import { SduiUseSpec, SduiAdapter, SduiRegistry, SduiCanSetting, SpecIssue, SduiPage, SduiPropValue, SduiChild } from '@wipco/sdui';
|
|
4
4
|
import { SduiComponentMeta, SduiPropMeta } from '@wipco/sdui/meta';
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* 실데이터 미리보기 어댑터 — 봉인 어댑터에서 **GET 하나만** 선별 개방한다.
|
|
8
|
+
*
|
|
9
|
+
* ## 무엇이 열리고 무엇이 닫힌 채인가
|
|
10
|
+
*
|
|
11
|
+
* `page.data` 조회는 어댑터 `fetch`를 전부 `method:'GET'`으로 탄다(SduiRenderer의
|
|
12
|
+
* page-data 경로). 봉인 어댑터가 fetch를 통째로 막아서 미리보기에 실데이터가 안 나오던
|
|
13
|
+
* 것인데, GET만 열면 **submitForm(DELETE)이 운영 데이터를 지운 사고 경로는 닫힌 채**
|
|
14
|
+
* 데이터가 흐른다. 나머지는 전부 봉인 유지다:
|
|
15
|
+
*
|
|
16
|
+
* - `rawFetch`(download) · `navigate` · `invalidate` · `refresh` · `subscribe` — 차단.
|
|
17
|
+
* - `replaceQuery` — no-op 유지(호스트 주소 보호).
|
|
18
|
+
* - `sandbox: true` 유지 — 자기 데이터 클라이언트로 직접 조회하는 컴포넌트
|
|
19
|
+
* (ERP `RemoteSearchResults` 류)는 실데이터 모드에서도 빈 표로 남는다. 그 캐시는
|
|
20
|
+
* 앱 전역 싱글턴이라 미리보기 응답이 실리면 편집기를 닫은 뒤 진짜 페이지까지
|
|
21
|
+
* 오염시킨다(어댑터 주석의 실측 근거). 반쪽이지만 문구로 밝히는 쪽을 골랐다.
|
|
22
|
+
* - `resolveAsset` — 동일 오리진 상대 URL만 통과시킨다. 실데이터를 보겠다고 켠
|
|
23
|
+
* 화면에서 자기 서버의 이미지(자산 사진 등)까지 체커보드면 "실데이터"가 아니게 되고,
|
|
24
|
+
* 그 요청은 GET과 같은 성질(편집자 세션의 읽기)이다. 바깥 호스트는 여전히
|
|
25
|
+
* 자리표시자다 — 외부로 쿠키·리퍼러를 실어 보낼 이유는 개방 후에도 없다.
|
|
26
|
+
*
|
|
27
|
+
* ## 오용이 타입으로 막히는 통로
|
|
28
|
+
*
|
|
29
|
+
* 호스트가 주입하는 {@link PreviewFetch}는 init이 `{ method: 'GET' }` 리터럴이라
|
|
30
|
+
* **GET 외 메서드를 넘기는 코드가 컴파일되지 않는다.** 뷰어에 어댑터를 통째로 주입하는
|
|
31
|
+
* `viewerAdapter`(무엇이든 열린다)와 달리, 이 통로는 아무리 잘못 배선해도 조회까지만
|
|
32
|
+
* 열린다 — DELETE /assets/AS-0042 사고와 이 통로가 다른 지점이 그것이다.
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* 미리보기 data 조회 통로 — **타입이 GET만 허용해 오용이 불가능하다.**
|
|
37
|
+
* ERP라면 `previewFetch={(path, init) => erpFetch(path, init)}` 한 줄이다.
|
|
38
|
+
*/
|
|
39
|
+
type PreviewFetch = (path: string, init: {
|
|
40
|
+
method: 'GET';
|
|
41
|
+
signal?: AbortSignal;
|
|
42
|
+
}) => Promise<unknown>;
|
|
43
|
+
interface PreviewEntityOption {
|
|
44
|
+
value: string;
|
|
45
|
+
label: string;
|
|
46
|
+
sublabel?: string;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* 패턴 스펙(`asset/asset/{id}`) 미리보기용 엔티티 검색 — 어느 엔드포인트를 뒤질지는
|
|
50
|
+
* 소비 프로젝트만 안다(스펙 id 접두 → 검색 API 맵은 호스트의 계약이다).
|
|
51
|
+
*/
|
|
52
|
+
type PreviewEntitySearch = (specId: string, paramName: string, query: string, signal?: AbortSignal) => Promise<PreviewEntityOption[]>;
|
|
53
|
+
/**
|
|
54
|
+
* GET 개방 어댑터. 봉인본(createCanvasAdapter)을 스프레드한 뒤 `fetch`와
|
|
55
|
+
* `resolveAsset`만 교체한다 — 차단 항목이 봉인본에 늘면 여기도 자동으로 는다
|
|
56
|
+
* (사본이 뒤처져 JSON 미리보기가 새던 전례의 재발 방지와 같은 원리).
|
|
57
|
+
*/
|
|
58
|
+
declare function createDataPreviewAdapter(previewFetch: PreviewFetch, onBlocked: (what: string) => void): SduiAdapter;
|
|
59
|
+
interface PreviewAdapterOptions {
|
|
60
|
+
/**
|
|
61
|
+
* 사용자의 **명시 발동**. 패널에서 실데이터 토글을 켰거나 엔티티를 지정했을 때만
|
|
62
|
+
* true다. 이 값 없이 previewFetch만으로 열리면 "호스트가 주입했다"가 곧 "항상
|
|
63
|
+
* 열린다"가 되어, 발동을 사용자에게 묻는다는 전제가 사라진다.
|
|
64
|
+
*/
|
|
65
|
+
armed: boolean;
|
|
66
|
+
/** 호스트 주입 통로. 없으면 armed여도 봉인 그대로다(열 방법 자체가 없다). */
|
|
67
|
+
previewFetch?: PreviewFetch;
|
|
68
|
+
onBlocked: (what: string) => void;
|
|
69
|
+
/** 편집기 자체 useSpec(use-spec.ts) — Fragment 렌더용. 봉인 여부와 무관하게 얹는다. */
|
|
70
|
+
useSpec?: SduiUseSpec;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* 미리보기 어댑터를 고르는 단일 게이트.
|
|
74
|
+
*
|
|
75
|
+
* 뷰 세 곳(캔버스·JSON 미리보기·뷰어)이 각자 `armed ? 개방 : 봉인` 삼항을 쓰면 그
|
|
76
|
+
* 조건이 사본 세 벌이 된다 — 봉인 어댑터의 사본이 뒤처져 새던 사고와 같은 모양이라,
|
|
77
|
+
* 게이트를 함수 하나로 모으고 테스트(sealed-screens)가 이 함수의 행동을 직접 잡는다.
|
|
78
|
+
*
|
|
79
|
+
* useSpec을 봉인·개방 양쪽에 항상 얹는 이유: 렌더 중 어댑터의 useSpec이 "있다가
|
|
80
|
+
* 없어지는" 교체는 훅 순서 위반이다(어댑터 계약 주석). armed 토글로 어댑터가 바뀌어도
|
|
81
|
+
* useSpec 자리는 유지되어야 한다.
|
|
82
|
+
*/
|
|
83
|
+
declare function resolvePreviewAdapter({ armed, previewFetch, onBlocked, useSpec, }: PreviewAdapterOptions): SduiAdapter;
|
|
84
|
+
|
|
6
85
|
/**
|
|
7
86
|
* 스펙 저장소 어댑터 계약.
|
|
8
87
|
*
|
|
@@ -163,6 +242,18 @@ declare class PageIdRejectedError extends Error {
|
|
|
163
242
|
*/
|
|
164
243
|
declare const PAGE_ID_PATTERN: RegExp;
|
|
165
244
|
declare function isValidPageId(id: string): boolean;
|
|
245
|
+
/**
|
|
246
|
+
* 다이얼로그 조각 스펙의 id 접두.
|
|
247
|
+
*
|
|
248
|
+
* 규칙이 아니라 **관례**다 — 저장소는 이 접두에 아무 의미를 두지 않고, 렌더러의
|
|
249
|
+
* Fragment도 어떤 id든 가져온다. 편집기만 이 관례를 읽어 목록 탭을 가르고
|
|
250
|
+
* (PageListView), 다이얼로그 미리보기의 열림 시딩을 기본으로 켠다(preview/seed.ts).
|
|
251
|
+
* ERP의 lint-specs·마이그레이션 0027/0028과 공유되는 이름이라 임의로 바꾸면 안 된다
|
|
252
|
+
* (계약: Fragment/id/args/$arg 어휘 고정과 같은 문서).
|
|
253
|
+
*/
|
|
254
|
+
declare const DIALOG_PREFIX = "dialogs/";
|
|
255
|
+
/** 이 id가 다이얼로그 조각 관례를 따르는가 — {@link DIALOG_PREFIX} 접두 검사. */
|
|
256
|
+
declare function isDialogSpecId(id: string): boolean;
|
|
166
257
|
/** 스펙에서 표시용 제목 뽑기 — 모든 어댑터가 같은 규칙을 써야 목록이 갈리지 않는다 */
|
|
167
258
|
declare function titleOf(spec: unknown): string | null;
|
|
168
259
|
|
|
@@ -333,6 +424,20 @@ interface SduiEditorProps {
|
|
|
333
424
|
* 이 값이 없어도 편집자를 오도하지 않는다 — 그래서 캔버스에는 넘기지 않는다.
|
|
334
425
|
*/
|
|
335
426
|
can?: SduiCanSetting;
|
|
427
|
+
/**
|
|
428
|
+
* 실데이터 미리보기의 조회 통로. `viewerAdapter`와 성질이 다르다 — 그쪽은 어댑터를
|
|
429
|
+
* 통째로 주입해 무엇이든 열리지만(그래서 "보기" 버튼 한 번이 DELETE를 내보낸 사고의
|
|
430
|
+
* 통로가 될 수 있었다), 이쪽은 **타입이 GET만 받고**({@link PreviewFetch}) 발동도
|
|
431
|
+
* 사용자가 시딩 패널에서 명시로 켠 때만이다. 캔버스·JSON 미리보기·뷰어 세 화면이
|
|
432
|
+
* 같은 게이트를 쓴다. ERP라면 `previewFetch={(path, init) => erpFetch(path, init)}`.
|
|
433
|
+
*/
|
|
434
|
+
previewFetch?: PreviewFetch;
|
|
435
|
+
/**
|
|
436
|
+
* 패턴 스펙(`asset/asset/{id}`) 미리보기용 엔티티 검색. 어느 엔드포인트를 뒤질지는
|
|
437
|
+
* 소비 프로젝트만 아는 정보라 훅으로 받는다 — 시딩 패널이 `route.<param>` 시드를
|
|
438
|
+
* 검색 선택으로 채운다.
|
|
439
|
+
*/
|
|
440
|
+
previewEntitySearch?: PreviewEntitySearch;
|
|
336
441
|
className?: string;
|
|
337
442
|
}
|
|
338
443
|
/**
|
|
@@ -351,7 +456,7 @@ interface SduiEditorProps {
|
|
|
351
456
|
* <SduiEditor store={store} />
|
|
352
457
|
* ```
|
|
353
458
|
*/
|
|
354
|
-
declare function SduiEditor({ store, view, onViewChange, defaultView, chrome, registry, catalog, onNavigate, viewerAdapter, can, className, }: SduiEditorProps): React.JSX.Element;
|
|
459
|
+
declare function SduiEditor({ store, view, onViewChange, defaultView, chrome, registry, catalog, onNavigate, viewerAdapter, can, previewFetch, previewEntitySearch, className, }: SduiEditorProps): React.JSX.Element;
|
|
355
460
|
|
|
356
461
|
interface PageListViewProps {
|
|
357
462
|
store: SpecStore;
|
|
@@ -383,8 +488,20 @@ interface EditorViewProps {
|
|
|
383
488
|
* 그려지되 팔레트에는 안 나온다.
|
|
384
489
|
*/
|
|
385
490
|
catalog?: Record<string, SduiComponentMeta>;
|
|
491
|
+
/**
|
|
492
|
+
* 다른 스펙을 **편집으로** 여는 위임 — 셸이 `openEdit`을 꽂는다. Fragment의 참조
|
|
493
|
+
* 열기(인스펙터)가 쓴다. 없으면 열기 버튼이 그려지지 않을 뿐 편집은 된다.
|
|
494
|
+
*/
|
|
495
|
+
onOpenSpec?: (id: string) => void;
|
|
496
|
+
/**
|
|
497
|
+
* 실데이터 미리보기의 조회 통로 — 타입이 GET만 받아 오용이 컴파일에서 막힌다.
|
|
498
|
+
* 발동은 사용자가 시딩 패널에서 명시로 켠 때만이다({@link resolvePreviewAdapter}).
|
|
499
|
+
*/
|
|
500
|
+
previewFetch?: PreviewFetch;
|
|
501
|
+
/** 패턴 스펙(`{id}` 세그먼트)의 엔티티 검색 — 시딩 패널의 route.* 자동완성. */
|
|
502
|
+
previewEntitySearch?: PreviewEntitySearch;
|
|
386
503
|
}
|
|
387
|
-
declare function EditorView({ store, id, onBack, onPreview, registry, catalog }: EditorViewProps): React__default.JSX.Element;
|
|
504
|
+
declare function EditorView({ store, id, onBack, onPreview, registry, catalog, onOpenSpec, previewFetch, previewEntitySearch, }: EditorViewProps): React__default.JSX.Element;
|
|
388
505
|
|
|
389
506
|
interface ViewerViewProps {
|
|
390
507
|
store: SpecStore;
|
|
@@ -444,6 +561,13 @@ interface ViewerViewProps {
|
|
|
444
561
|
* 화면에서 권한 재단만 빠진다.
|
|
445
562
|
*/
|
|
446
563
|
can?: SduiCanSetting;
|
|
564
|
+
/**
|
|
565
|
+
* 실데이터 미리보기의 조회 통로 — GET만 받는 타입이라 `viewerAdapter` 주입과 달리
|
|
566
|
+
* 아무리 잘못 배선해도 조회까지만 열린다. 발동은 시딩 패널의 명시 조작뿐이다.
|
|
567
|
+
*/
|
|
568
|
+
previewFetch?: PreviewFetch;
|
|
569
|
+
/** 패턴 스펙 미리보기용 엔티티 검색 — 시딩 패널의 route.* 자동완성. */
|
|
570
|
+
previewEntitySearch?: PreviewEntitySearch;
|
|
447
571
|
}
|
|
448
572
|
/**
|
|
449
573
|
* 페이지 뷰어 — 저장된 스펙을 실제 소비 화면처럼 렌더링한다.
|
|
@@ -454,7 +578,7 @@ interface ViewerViewProps {
|
|
|
454
578
|
*
|
|
455
579
|
* 부작용 차단은 캔버스와 **같다**. {@link ViewerViewProps.adapter} 참고.
|
|
456
580
|
*/
|
|
457
|
-
declare function ViewerView({ store, id, onBack, onEdit, onNavigate, registry, adapter: hostAdapter, can, }: ViewerViewProps): React__default.JSX.Element;
|
|
581
|
+
declare function ViewerView({ store, id, onBack, onEdit, onNavigate, registry, adapter: hostAdapter, can, previewFetch, previewEntitySearch, }: ViewerViewProps): React__default.JSX.Element;
|
|
458
582
|
|
|
459
583
|
/**
|
|
460
584
|
* 새 페이지 생성 템플릿 — 스펙 문법 견본을 겸한다.
|
|
@@ -477,6 +601,174 @@ type GradedIssue = SpecIssue & {
|
|
|
477
601
|
};
|
|
478
602
|
declare function gradeIssues(spec: unknown): GradedIssue[];
|
|
479
603
|
|
|
604
|
+
/**
|
|
605
|
+
* 미리보기 시딩 — **순수 모듈**(DOM·React 없음, node:test로 그대로 검증된다).
|
|
606
|
+
*
|
|
607
|
+
* ## 왜 시딩이 필요한가
|
|
608
|
+
*
|
|
609
|
+
* `Dialog`에는 `open` 프롭이 없다. 스펙은 `Show(when: {"$state": key})`로 감싸 열림을
|
|
610
|
+
* 상태로 제어한다(실측: body 최상위 1위가 Show 153회, 대부분 Dialog). 캔버스는
|
|
611
|
+
* `EditShow`가 조건을 무시해 이미 보이지만, **JSON 미리보기와 뷰어는 진짜 조건을
|
|
612
|
+
* 지키므로** 상태가 빈 채로 열면 `when`이 falsy → 백지가 된다.
|
|
613
|
+
*
|
|
614
|
+
* 캔버스가 자동 시딩을 기각한 근거(edit-runtime.tsx: `$calc` 조건은 무엇을 켜야 할지
|
|
615
|
+
* 판정할 수 없고, 두 Show가 같은 키를 반대로 보면 모순이 난다)는 **캔버스의 것**이다 —
|
|
616
|
+
* 여기서는 "최상위 Show + 순수 `$state` 참조 + 안에 Dialog"라는 좁은 경우만 자동으로
|
|
617
|
+
* 켜고, 나머지는 수동 패널(PreviewSeedPanel)로 넘긴다. 그 좁은 경우에는 위 반론이
|
|
618
|
+
* 성립하지 않는다.
|
|
619
|
+
*
|
|
620
|
+
* ## args 샘플은 왜 "래퍼 페이지"인가 (계약 §7 방식 채택 근거)
|
|
621
|
+
*
|
|
622
|
+
* `$arg`는 Fragment가 렌더될 때 쌓는 args 프레임에서만 읽힌다 — `initialState`는
|
|
623
|
+
* `$state`만 심을 수 있고, 렌더러에 args 프레임을 밖에서 주입하는 통로는 없다(일부러
|
|
624
|
+
* 없다: 프레임은 호출부 스코프와 짝이라 밖에서 지어내면 해석 스코프가 거짓이 된다).
|
|
625
|
+
* 그래서 대안을 비교할 것도 없이, **현재 스펙을 Fragment 노드로 감싼 임시 페이지**를
|
|
626
|
+
* 미리보기에 태우는 것이 렌더러 무수정으로 가능한 유일한 방식이면서 동시에 가장
|
|
627
|
+
* 정확하다 — args 전달·$arg 해석·액션 치환까지 전부 **실제 코드 경로**로 검증된다.
|
|
628
|
+
*/
|
|
629
|
+
|
|
630
|
+
/**
|
|
631
|
+
* dialogs/ 스펙의 열림 조건 키를 찾는다.
|
|
632
|
+
*
|
|
633
|
+
* **최상위** `Show(when: {"$state": k})` 아래에 Dialog가 있을 때만 k를 시드로 삼는다.
|
|
634
|
+
* - `$calc`·비교식은 제외한다 — 무엇을 켜야 참이 되는지 판정할 수 없다(캔버스가 자동
|
|
635
|
+
* 시딩 전체를 기각한 바로 그 근거라, 그 부류는 수동 패널로 넘긴다).
|
|
636
|
+
* - `default`가 딸린 `{"$state": k, "default": …}`는 허용한다 — 여전히 키 하나를 켜면
|
|
637
|
+
* 열리는 순수 참조다. 그 밖의 형제 키가 있으면 순수 참조가 아니므로 제외한다.
|
|
638
|
+
* - 깊은 곳의 Show는 보지 않는다 — 중첩 조건은 "켜면 열린다"를 보장할 수 없다.
|
|
639
|
+
*/
|
|
640
|
+
declare function dialogOpenSeeds(spec: unknown): Record<string, true>;
|
|
641
|
+
/**
|
|
642
|
+
* 시딩 서명 — `SduiRenderer`의 `key`에 섞어 재마운트를 촉발한다.
|
|
643
|
+
*
|
|
644
|
+
* `initialState`는 마운트 1회 게으른 초기화라(SduiRenderer.tsx) 값만 바꿔서는 반영되지
|
|
645
|
+
* 않는다 — key가 바뀌어야 새로 심긴다. 키를 정렬해 직렬화하므로 같은 내용이면 삽입
|
|
646
|
+
* 순서가 달라도 같은 서명이다(불필요한 재마운트를 막는다).
|
|
647
|
+
*/
|
|
648
|
+
declare function seedSignature(seeds: Readonly<Record<string, SduiPropValue>>): string;
|
|
649
|
+
/** 수동 시드 한 행 — 값은 JSON 리터럴 텍스트로 든다(파싱은 {@link parseSeedValue}). */
|
|
650
|
+
interface ManualSeed {
|
|
651
|
+
readonly key: string;
|
|
652
|
+
readonly text: string;
|
|
653
|
+
}
|
|
654
|
+
/**
|
|
655
|
+
* 미리보기 시딩 패널의 전체 상태. 뷰(EditorView·ViewerView)가 들고 패널이 고친다.
|
|
656
|
+
*
|
|
657
|
+
* 한 덩어리인 이유: 자동 열림·수동 시드·args·실데이터가 각각 상태면 뷰마다 4개의
|
|
658
|
+
* useState와 4벌의 배선이 생기고, "엔티티를 고르면 시드도 넣고 실데이터도 켠다"처럼
|
|
659
|
+
* 두 조각을 함께 바꾸는 조작이 두 번의 setState로 갈라진다.
|
|
660
|
+
*/
|
|
661
|
+
interface PreviewSetup {
|
|
662
|
+
/** dialogs/ 스펙의 자동 열림 시딩을 쓸지. 기본 켬 — 백지 미리보기가 기본이면 안 된다. */
|
|
663
|
+
readonly autoOpen: boolean;
|
|
664
|
+
readonly manual: readonly ManualSeed[];
|
|
665
|
+
/** args 샘플 래퍼 사용 여부 — 켜면 현재 스펙을 Fragment로 감싼 임시 페이지를 그린다. */
|
|
666
|
+
readonly argsOn: boolean;
|
|
667
|
+
/** args 오브젝트의 JSON 텍스트. 파싱 실패면 래퍼를 적용하지 않는다(패널이 알린다). */
|
|
668
|
+
readonly argsText: string;
|
|
669
|
+
/** 실데이터 조회 발동 — 사용자가 명시로 켰거나 엔티티를 지정했을 때만 true다. */
|
|
670
|
+
readonly dataArmed: boolean;
|
|
671
|
+
/** 엔티티 검색에서 고른 표시 라벨(파라미터명 → 라벨). 선택됨 카드 복원용이다. */
|
|
672
|
+
readonly entityLabels: Readonly<Record<string, string>>;
|
|
673
|
+
}
|
|
674
|
+
declare const INITIAL_PREVIEW_SETUP: PreviewSetup;
|
|
675
|
+
/**
|
|
676
|
+
* 수동 시드 값 텍스트 → 값. JSON 리터럴로 읽고(`true`·`3`·`"a"`·`{...}`),
|
|
677
|
+
* 못 읽으면 **문자열 그대로** 쓴다 — `route.id` 자리에 `AS-0042`를 따옴표 없이
|
|
678
|
+
* 쳐도 동작해야 한다(따옴표를 강요하면 첫 사용에서 반드시 걸려 넘어진다).
|
|
679
|
+
*/
|
|
680
|
+
declare function parseSeedValue(text: string): SduiPropValue;
|
|
681
|
+
/** 패널 상태 + 자동 시드 → `initialState`. 수동 행이 자동 시드를 덮는다(사용자가 임자다). */
|
|
682
|
+
declare function seedsOf(setup: PreviewSetup, autoSeeds: Readonly<Record<string, true>>): Record<string, SduiPropValue>;
|
|
683
|
+
/**
|
|
684
|
+
* 현재 스펙을 Fragment 노드로 감싼 임시 미리보기 페이지.
|
|
685
|
+
*
|
|
686
|
+
* `useSpec`이 `specId`에 현재 편집 중 본문을 돌려주면(use-spec.ts의 override 자리),
|
|
687
|
+
* 이 페이지 하나로 args 전달 → args 프레임 → `$arg` 해석까지 실제 렌더러 경로가
|
|
688
|
+
* 그대로 돈다. 채택 근거는 파일 머리말 참고.
|
|
689
|
+
*
|
|
690
|
+
* @returns argsText가 평면 오브젝트로 읽히면 래퍼 페이지, 아니면 null(래퍼 미적용).
|
|
691
|
+
*/
|
|
692
|
+
declare function argsWrapperPage(specId: string, argsText: string): {
|
|
693
|
+
page: SduiPage;
|
|
694
|
+
args: Record<string, unknown>;
|
|
695
|
+
} | null;
|
|
696
|
+
/**
|
|
697
|
+
* 스펙 JSON에서 `$state` 키를 모은다 — 수동 시드 키 입력의 datalist 재료.
|
|
698
|
+
*
|
|
699
|
+
* `buildStateKeyIndex`(builder/selectors.ts)를 안 쓰는 이유: 그쪽은 `BuilderDoc`을
|
|
700
|
+
* 받는데, JSON 모드 미리보기와 뷰어에는 편집 트리가 없다(파싱된 스펙뿐이다).
|
|
701
|
+
* 스펙을 트리로 옮겨서까지 쓸 일이 아니다 — 여기 필요한 것은 인덱스가 아니라
|
|
702
|
+
* 키 목록 하나다. 많이 쓰인 키를 앞에 준다(자동완성에서 기대하는 순서).
|
|
703
|
+
*/
|
|
704
|
+
declare function collectStateKeys(spec: unknown, limit?: number): string[];
|
|
705
|
+
/**
|
|
706
|
+
* 스펙 id의 패턴 파라미터 이름들 — `asset/asset/{id}` → `['id']`.
|
|
707
|
+
*
|
|
708
|
+
* ERP 런타임이 이 이름으로 `route.<이름>`을 `initialState`에 심는 계약이라
|
|
709
|
+
* (SduiPage.tsx), 미리보기의 엔티티 시딩도 같은 이름을 쓴다.
|
|
710
|
+
*/
|
|
711
|
+
declare function patternParams(specId: string): string[];
|
|
712
|
+
|
|
713
|
+
/**
|
|
714
|
+
* 편집기 자체 `useSpec` — Fragment 포함 페이지가 **편집기 미리보기에서도** 그려지게 한다.
|
|
715
|
+
*
|
|
716
|
+
* 렌더러의 Fragment는 어댑터 훅 `useSpec(id)`으로 조각 스펙을 가져온다(없으면
|
|
717
|
+
* warnOnce + 무렌더). 편집기의 세 미리보기(캔버스·JSON 미리보기·뷰어)는 봉인 어댑터를
|
|
718
|
+
* 쓰는데, 그 봉인에 useSpec까지 비워 두면 dialogs/ 조각을 끼운 페이지가 편집기에서만
|
|
719
|
+
* 백지가 된다 — "보이는 대로 고친다"가 Fragment 하나에 무너진다.
|
|
720
|
+
*
|
|
721
|
+
* ## 봉인 정책과 충돌하지 않는 근거 (여기에 명시해 둔다)
|
|
722
|
+
*
|
|
723
|
+
* 봉인 어댑터가 막는 것은 "저장도 안 된 스펙이 **편집자의 특권 세션으로 운영 API**를
|
|
724
|
+
* 부르는 것"이다(submitForm의 DELETE가 실제 데이터를 지운 전례). 스펙 읽기는 그 부류가
|
|
725
|
+
* 아니다 — `SpecStore.read`(ERP `GET /ui/pages/{id}`)는 **읽기 전용**이고, 편집기가
|
|
726
|
+
* 이미 같은 세션·같은 권한(`setting.update`)으로 목록·편집을 위해 상시 호출하는
|
|
727
|
+
* 경로다. 스펙을 읽지 못하면 편집기 자체가 성립하지 않으므로, 이 통로는 봉인의 예외가
|
|
728
|
+
* 아니라 봉인 바깥이다. 어댑터의 `fetch` 차단(운영 데이터 API)은 그대로 유지된다.
|
|
729
|
+
*
|
|
730
|
+
* ## 왜 팩토리 + 클로저 캐시인가
|
|
731
|
+
*
|
|
732
|
+
* - 훅 규칙: 렌더러는 어댑터의 useSpec을 컴포넌트(SduiFragmentBody)에서 부른다.
|
|
733
|
+
* 훅 함수의 정체성이 렌더마다 바뀌어도 되지만, **캐시가 함께 초기화되면** 조각마다
|
|
734
|
+
* 매 렌더 재조회가 난다. 그래서 뷰가 `useMemo(() => createEditorUseSpec(store), [store])`
|
|
735
|
+
* 로 한 번 만들고, 캐시 수명 = 그 화면의 수명이다(편집기 미리보기는 저장 전 상태를
|
|
736
|
+
* 보는 자리라, 조각의 서버 측 변경을 실시간 반영할 이유가 없다 — 다시 열면 새로 읽는다).
|
|
737
|
+
* - override 게터: args 샘플 래퍼(seed.ts의 `argsWrapperPage`)가 "현재 편집 중 본문"을
|
|
738
|
+
* 조각으로 쓴다. 편집 텍스트는 타이핑마다 바뀌므로 팩토리 인자로 값을 받으면 캐시가
|
|
739
|
+
* 같이 버려진다 — **안정된 게터**로 받아 호출 시점에 최신을 읽는다.
|
|
740
|
+
*/
|
|
741
|
+
|
|
742
|
+
/**
|
|
743
|
+
* 스토어 read 기반 useSpec 훅을 만든다.
|
|
744
|
+
*
|
|
745
|
+
* 반환 계약은 어댑터 문서 그대로: `undefined` = 로딩(무렌더·무경고), `null` = 없음/실패
|
|
746
|
+
* (렌더러가 warnOnce), 그 외 = 스펙.
|
|
747
|
+
*
|
|
748
|
+
* @param getOverride id에 대해 스펙을 직접 줄 자리(현재 편집 중 본문 등).
|
|
749
|
+
* `undefined`를 돌려주면 스토어 경로로 넘어간다. **안정된 함수**여야
|
|
750
|
+
* 한다(ref를 읽는 useCallback) — 게터가 바뀌면 훅을 새로 만들 이유가
|
|
751
|
+
* 없는데도 어댑터 정체성이 흔들린다.
|
|
752
|
+
*/
|
|
753
|
+
declare function createEditorUseSpec(store: SpecStore, getOverride?: (id: string) => SduiPage | null | undefined): SduiUseSpec;
|
|
754
|
+
|
|
755
|
+
interface PreviewSeedPanelProps {
|
|
756
|
+
/** 미리보기 대상 스펙 id — 패턴 파라미터(`{id}`)와 엔티티 검색 라우팅의 재료. */
|
|
757
|
+
specId: string;
|
|
758
|
+
/** 자동 열림 시딩으로 찾은 키들(dialogs/ 스펙의 최상위 Show 패턴). 빈 객체면 해당 없음. */
|
|
759
|
+
autoSeeds: Readonly<Record<string, true>>;
|
|
760
|
+
/** 수동 시드 키 입력의 datalist 재료 — 스펙에서 모은 `$state` 키들. */
|
|
761
|
+
stateKeys: readonly string[];
|
|
762
|
+
value: PreviewSetup;
|
|
763
|
+
onChange: (next: PreviewSetup) => void;
|
|
764
|
+
/** 호스트의 엔티티 검색 훅. 없으면 검색 칸 대신 안내를 그린다. */
|
|
765
|
+
previewEntitySearch?: PreviewEntitySearch;
|
|
766
|
+
/** 호스트가 previewFetch를 주입했는가 — 없으면 실데이터 토글을 잠그고 이유를 밝힌다. */
|
|
767
|
+
canFetch: boolean;
|
|
768
|
+
onClose: () => void;
|
|
769
|
+
}
|
|
770
|
+
declare function PreviewSeedPanel({ specId, autoSeeds, stateKeys, value, onChange, previewEntitySearch, canFetch, onClose, }: PreviewSeedPanelProps): React.JSX.Element;
|
|
771
|
+
|
|
480
772
|
/**
|
|
481
773
|
* 시각 빌더의 **문서 모델** — 편집 중인 페이지의 자료구조와 변형 연산.
|
|
482
774
|
*
|
|
@@ -1043,6 +1335,19 @@ interface BuilderViewProps {
|
|
|
1043
1335
|
readonly onSave?: () => void;
|
|
1044
1336
|
/** `navigate` 액션 자동완성에 쓸 다른 페이지 id들 — `SpecStore.list()`의 결과. */
|
|
1045
1337
|
readonly pageIds?: readonly string[];
|
|
1338
|
+
/**
|
|
1339
|
+
* Fragment의 참조 스펙을 편집으로 여는 위임 — 인스펙터의 FragmentRefRow로 흘린다.
|
|
1340
|
+
* `pageIds`와 같은 길(EditorView → 여기 → 소비 지점)을 탄다.
|
|
1341
|
+
*/
|
|
1342
|
+
readonly onOpenSpec?: (id: string) => void;
|
|
1343
|
+
/** 편집기 자체 useSpec — 캔버스가 Fragment 조각을 그릴 수 있게 봉인 어댑터에 얹는다. */
|
|
1344
|
+
readonly useSpec?: SduiUseSpec;
|
|
1345
|
+
/** 실데이터 미리보기 재료 — 캔버스 어댑터의 GET 개방에 쓴다({@link CanvasProps} 참고). */
|
|
1346
|
+
readonly previewFetch?: PreviewFetch;
|
|
1347
|
+
/** 실데이터 발동(사용자 명시). 시딩 패널의 토글·엔티티 지정에서만 켜진다. */
|
|
1348
|
+
readonly dataArmed?: boolean;
|
|
1349
|
+
/** 미리보기 시드 — 캔버스 렌더러의 `initialState`로 내려간다(변경 시 재마운트). */
|
|
1350
|
+
readonly canvasInitialState?: Record<string, SduiPropValue>;
|
|
1046
1351
|
/**
|
|
1047
1352
|
* 캔버스가 그릴 때 쓸 레지스트리. 생략하면 {@link editorRegistry}(라이브러리 어휘
|
|
1048
1353
|
* 66종 + 렌더러 내장 `ForEach`)다. 소비 앱이 자기 컴포넌트를 얹었다면 **그 레지스트리를
|
|
@@ -1055,7 +1360,7 @@ interface BuilderViewProps {
|
|
|
1055
1360
|
readonly can?: SduiCanSetting;
|
|
1056
1361
|
readonly className?: string;
|
|
1057
1362
|
}
|
|
1058
|
-
declare function BuilderView({ spec, syncKey, onSpecChange, onOpenJson, onSave, pageIds, registry, catalog, can, className, }: BuilderViewProps): React__default.JSX.Element;
|
|
1363
|
+
declare function BuilderView({ spec, syncKey, onSpecChange, onOpenJson, onSave, pageIds, onOpenSpec, useSpec, previewFetch, dataArmed, canvasInitialState, registry, catalog, can, className, }: BuilderViewProps): React__default.JSX.Element;
|
|
1059
1364
|
|
|
1060
1365
|
/**
|
|
1061
1366
|
* 편집 화면이 레지스트리를 못 받았을 때 쓰는 **기본 어휘** — 그리고 그것 하나뿐이다.
|
|
@@ -1184,6 +1489,28 @@ interface CanvasProps {
|
|
|
1184
1489
|
registry?: SduiRegistry;
|
|
1185
1490
|
/** `Can`의 판정. 캔버스는 게이트를 열어 두므로 보통 넘길 일이 없다. */
|
|
1186
1491
|
can?: SduiCanSetting;
|
|
1492
|
+
/**
|
|
1493
|
+
* 편집기 자체 useSpec — Fragment 조각이 캔버스에서도 그려지게 봉인 어댑터에 얹는다.
|
|
1494
|
+
* 스펙 읽기는 편집자 인증의 읽기 전용 경로라 봉인 정책과 충돌하지 않는다(use-spec.ts).
|
|
1495
|
+
*/
|
|
1496
|
+
useSpec?: SduiUseSpec;
|
|
1497
|
+
/**
|
|
1498
|
+
* 실데이터 미리보기 재료 두 개.
|
|
1499
|
+
*
|
|
1500
|
+
* **완제품 어댑터가 아니라 재료를 받는 이유**: 차단 알림은 캔버스 자신의 공지줄에
|
|
1501
|
+
* 떠야 한다. 바깥에서 지은 어댑터를 통째로 받으면 그 어댑터의 onBlocked가 다른
|
|
1502
|
+
* 화면(JSON 미리보기의 공지줄)을 가리켜, 캔버스에서 막힌 동작이 소리 없이 사라진다.
|
|
1503
|
+
* 어댑터를 짓는 책임은 캔버스에 남기고({@link resolvePreviewAdapter} — 봉인 기본),
|
|
1504
|
+
* 발동 여부와 통로만 내려받는다.
|
|
1505
|
+
*/
|
|
1506
|
+
previewFetch?: PreviewFetch;
|
|
1507
|
+
/** 실데이터 발동(사용자 명시). 없거나 false면 기존 봉인 그대로다. */
|
|
1508
|
+
dataArmed?: boolean;
|
|
1509
|
+
/**
|
|
1510
|
+
* 미리보기 시드 — 렌더러의 `initialState`. 마운트 1회 계약이라 값이 바뀌면
|
|
1511
|
+
* 캔버스가 렌더러를 key로 갈아 끼운다(편집 트리·선택은 렌더러 밖이라 무사하다).
|
|
1512
|
+
*/
|
|
1513
|
+
initialState?: Record<string, SduiPropValue>;
|
|
1187
1514
|
className?: string;
|
|
1188
1515
|
}
|
|
1189
1516
|
declare function Canvas({ doc, catalog, selection, hover, dispatch,
|
|
@@ -1195,7 +1522,7 @@ declare function Canvas({ doc, catalog, selection, hover, dispatch,
|
|
|
1195
1522
|
* 캔버스는 "등록되지 않은 컴포넌트: Timeline"이라 답하는데, 왜 다른지 설명하는 것이
|
|
1196
1523
|
* 화면 어디에도 없다 — 소비자는 "라이브러리에 없구나"로 오귀인한다.
|
|
1197
1524
|
*/
|
|
1198
|
-
registry, can, className, }: CanvasProps): React.JSX.Element;
|
|
1525
|
+
registry, can, useSpec, previewFetch, dataArmed, initialState, className, }: CanvasProps): React.JSX.Element;
|
|
1199
1526
|
|
|
1200
1527
|
interface PaletteProps {
|
|
1201
1528
|
doc: BuilderDoc;
|
|
@@ -1249,9 +1576,20 @@ interface InspectorProps {
|
|
|
1249
1576
|
readonly onRequestBinding?: (propName: string) => void;
|
|
1250
1577
|
/** 노드의 React `key`까지 편집할 수 있게 한다. 기본 true. */
|
|
1251
1578
|
readonly allowKeyEdit?: boolean;
|
|
1579
|
+
/**
|
|
1580
|
+
* 저장소의 스펙 id 목록 — Fragment의 참조 존재 검사와 `id` 프롭 자동완성 재료.
|
|
1581
|
+
* `navigate` 자동완성이 이미 타는 길(EditorView의 `store.list()`)과 같은 재료라
|
|
1582
|
+
* 없어도 편집은 된다.
|
|
1583
|
+
*/
|
|
1584
|
+
readonly pageIds?: readonly string[];
|
|
1585
|
+
/**
|
|
1586
|
+
* Fragment의 참조 스펙을 편집으로 여는 위임 — 셸이 `openEdit`을 꽂는다.
|
|
1587
|
+
* 라우팅은 기존 제어 모드가 그대로 처리하므로 인스펙터는 id만 넘긴다.
|
|
1588
|
+
*/
|
|
1589
|
+
readonly onOpenSpec?: (id: string) => void;
|
|
1252
1590
|
readonly className?: string;
|
|
1253
1591
|
}
|
|
1254
|
-
declare function Inspector({ doc, catalog, selection, onApply, onRequestBinding, allowKeyEdit, className, }: InspectorProps): React.JSX.Element;
|
|
1592
|
+
declare function Inspector({ doc, catalog, selection, onApply, onRequestBinding, allowKeyEdit, pageIds, onOpenSpec, className, }: InspectorProps): React.JSX.Element;
|
|
1255
1593
|
|
|
1256
1594
|
/**
|
|
1257
1595
|
* 편집 문서에서 **화면이 필요로 하는 것들을 뽑아내는** 파생 조회.
|
|
@@ -1766,4 +2104,4 @@ declare function formatAction(action: ActionValue): string;
|
|
|
1766
2104
|
/** 액션 목록 전체를 한 줄로 — 프롭 목록에서 "무엇이 붙어 있나"를 볼 때. */
|
|
1767
2105
|
declare function formatActionList(actions: readonly ActionValue[]): string;
|
|
1768
2106
|
|
|
1769
|
-
export { ActionEditor, type ActionEditorProps, type ActionList, type ActionValue, type BindingContext, BindingEditor, type BindingEditorProps, type BindingSource, type BuilderChild, type BuilderDoc, type BuilderFidelity, type BuilderNode, type BuilderPageMeta, type BuilderText, BuilderView, type BuilderViewProps, COALESCE_WINDOW_MS, Canvas, type CanvasProps, type ChildLabel, DEFAULT_SLOT, type DropDomContext, type DropTarget, type DropVerdict, EMPTY_SELECTION, type EditorAction, type EditorState, EditorView, type EditorViewProps, type FlattenOptions, type GradedIssue, HISTORY_LIMIT, HistoryBar, type HistoryBarProps, type HistoryEntry, Inspector, type InspectorChange, type InspectorProps, type NodeId, PAGE_ID_PATTERN, PageExistsError, PageGoneError, PageIdConflictError, PageIdRejectedError, PageListView, type PageListViewProps, type PageMeta, type PageRecord, type PageRevision, type PageTemplate, Palette, type PaletteProps, ROOT_ID, RestSpecStore, type RestStoreConfig, SPEC_PAIR_FREQ, type SduiCatalog, SduiEditor, type SduiEditorProps, type SduiEditorView, type Selection, type SlotDescriptor, type SpecStore, type StateKeyEntry, type StateKeyIndex, type StateKeyNode, type StateKeyOrigin, type StoreCapabilities, StoreUnauthorizedError, StoreUnavailableError, StoreUnsupportedError, TEMPLATES, TEXT_CHILD, type TransformResult, type TreeRow, type TreeRowKind, TreeView, type TreeViewProps, type VersionExpectation, VersionMismatchError, ViewerView, type ViewerViewProps, type WriteOptions, addressOf, ancestorIdsOf, bindingContextFor, breadcrumbOf, buildStateKeyIndex, builderFidelity, canDrop, canDropAt, canMoveTo, canRedo, canUndo, createBindingContext, createBindingSource, createEditorState, createRestSpecStore, describeChild, dropFrequency, dropTargetsAround, duplicate, editorReducer, editorRegistry, emptyDoc, flattenTree, formatAction, formatActionList, formatValue, fromPage, getChild, getNode, gradeIssues, inDocumentOrder, insert, isDescendantOf, isMultiSelection, isSelected, isTypingTarget, isValidPageId, looksLikeActionProp, move, readActionList, recommendedChildren, redoLabel, remove, replaceChild, sameInsertionPoint, sameSpecMeaning, setChildren, setNodeKey, setPageMeta, setProp, setProps, setText, slotsOf, specOf, stateKeyStatus, suggestStateKeys, titleOf, toPage, toSpec, topmost, undoLabel, useUndoRedoShortcuts, walkDoc, writeActionList };
|
|
2107
|
+
export { ActionEditor, type ActionEditorProps, type ActionList, type ActionValue, type BindingContext, BindingEditor, type BindingEditorProps, type BindingSource, type BuilderChild, type BuilderDoc, type BuilderFidelity, type BuilderNode, type BuilderPageMeta, type BuilderText, BuilderView, type BuilderViewProps, COALESCE_WINDOW_MS, Canvas, type CanvasProps, type ChildLabel, DEFAULT_SLOT, DIALOG_PREFIX, type DropDomContext, type DropTarget, type DropVerdict, EMPTY_SELECTION, type EditorAction, type EditorState, EditorView, type EditorViewProps, type FlattenOptions, type GradedIssue, HISTORY_LIMIT, HistoryBar, type HistoryBarProps, type HistoryEntry, INITIAL_PREVIEW_SETUP, Inspector, type InspectorChange, type InspectorProps, type ManualSeed, type NodeId, PAGE_ID_PATTERN, PageExistsError, PageGoneError, PageIdConflictError, PageIdRejectedError, PageListView, type PageListViewProps, type PageMeta, type PageRecord, type PageRevision, type PageTemplate, Palette, type PaletteProps, type PreviewAdapterOptions, type PreviewEntityOption, type PreviewEntitySearch, type PreviewFetch, PreviewSeedPanel, type PreviewSeedPanelProps, type PreviewSetup, ROOT_ID, RestSpecStore, type RestStoreConfig, SPEC_PAIR_FREQ, type SduiCatalog, SduiEditor, type SduiEditorProps, type SduiEditorView, type Selection, type SlotDescriptor, type SpecStore, type StateKeyEntry, type StateKeyIndex, type StateKeyNode, type StateKeyOrigin, type StoreCapabilities, StoreUnauthorizedError, StoreUnavailableError, StoreUnsupportedError, TEMPLATES, TEXT_CHILD, type TransformResult, type TreeRow, type TreeRowKind, TreeView, type TreeViewProps, type VersionExpectation, VersionMismatchError, ViewerView, type ViewerViewProps, type WriteOptions, addressOf, ancestorIdsOf, argsWrapperPage, bindingContextFor, breadcrumbOf, buildStateKeyIndex, builderFidelity, canDrop, canDropAt, canMoveTo, canRedo, canUndo, collectStateKeys, createBindingContext, createBindingSource, createDataPreviewAdapter, createEditorState, createEditorUseSpec, createRestSpecStore, describeChild, dialogOpenSeeds, dropFrequency, dropTargetsAround, duplicate, editorReducer, editorRegistry, emptyDoc, flattenTree, formatAction, formatActionList, formatValue, fromPage, getChild, getNode, gradeIssues, inDocumentOrder, insert, isDescendantOf, isDialogSpecId, isMultiSelection, isSelected, isTypingTarget, isValidPageId, looksLikeActionProp, move, parseSeedValue, patternParams, readActionList, recommendedChildren, redoLabel, remove, replaceChild, resolvePreviewAdapter, sameInsertionPoint, sameSpecMeaning, seedSignature, seedsOf, setChildren, setNodeKey, setPageMeta, setProp, setProps, setText, slotsOf, specOf, stateKeyStatus, suggestStateKeys, titleOf, toPage, toSpec, topmost, undoLabel, useUndoRedoShortcuts, walkDoc, writeActionList };
|