@designbasekorea/wordpress-ui 0.1.5 → 0.1.7

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.
@@ -2,7 +2,8 @@
2
2
 
3
3
  이 문서는 `@designbasekorea/wordpress-ui`를 WordPress 플러그인과 테마의 관리자 화면에 적용하는 표준 가이드입니다.
4
4
 
5
- 이 가이드의 기준 배포 버전은 `0.1.5`입니다. 플러그인 또는 테마의 lockfile과
5
+ 이 가이드의 기준 배포 버전은 `0.1.7`입니다. `@designbasekorea/ui-wc@0.8.7`과
6
+ 같은 세트를 사용하세요. 플러그인 또는 테마의 lockfile과
6
7
  vendor 산출물도 같은 버전으로 맞추고, 버전을 올릴 때마다 아래 검증 명령을 다시
7
8
  실행합니다.
8
9
 
@@ -39,7 +40,7 @@ WordPress plugin/theme
39
40
 
40
41
  ### 1.1 WordPress 전역 관리자와 플러그인 내부 shell의 경계
41
42
 
42
- `AdminShell`과 `AdminSidebar`는 플러그인 또는 테마 내부 화면을 위한 것입니다. 다음 전역 요소는 수정하지 않습니다.
43
+ `db-admin-shell`과 React `AdminShell`은 플러그인 또는 테마 **내부 화면**을 위한 것입니다. 다음 전역 요소는 수정하지 않습니다.
43
44
 
44
45
  - `#adminmenu`
45
46
  - `#wpadminbar`
@@ -62,7 +63,7 @@ WordPress plugin/theme
62
63
  ### 2.1 Node 프로젝트에 설치
63
64
 
64
65
  ```bash
65
- npm install @designbasekorea/wordpress-ui@0.1.5
66
+ npm install @designbasekorea/wordpress-ui@0.1.7
66
67
  ```
67
68
 
68
69
  WordPress 서버가 npm을 실행하는 것이 아닙니다. 라이브러리를 설치한 뒤 플러그인 또는 테마 빌드 과정에서 배포에 필요한 파일을 포함해야 합니다.
@@ -143,7 +144,7 @@ require_once __DIR__ . '/vendor/wordpress-ui/wordpress-ui.php';
143
144
 
144
145
  final class MyPlugin_Admin_Assets
145
146
  {
146
- private const UI_VERSION = '0.1.5';
147
+ private const UI_VERSION = '0.1.7';
147
148
 
148
149
  public static function init(): void
149
150
  {
@@ -255,11 +256,42 @@ add_action('admin_enqueue_scripts', static function (string $hook_suffix): void
255
256
  - `admin_enqueue_scripts`에서만 관리자 자산을 등록합니다.
256
257
  - 현재 화면이 허용된 화면일 때만 `styles.css`와 `browser.iife.js`를 enqueue합니다.
257
258
  - WordPress 전역 관리자 화면에 자산을 무조건 enqueue하지 않습니다.
258
- - `browser.iife.js`는 `styles.css`보다 먼저 또는 함께 등록되어야 하며, 플러그인 JS는 `myplugin-wordpress-ui-browser`에 의존합니다.
259
+ - `browser.iife.js`는 `styles.css`와 함께 등록하고, **head에서 blocking**으로 로드합니다. footer/`defer`면 `db-*`가 빈 태그로 보이다가 늦게 그려집니다.
260
+ - 플러그인 admin.js는 footer에 두되 handle `…-wordpress-ui-browser`에 의존합니다.
259
261
  - 버전은 패키지 버전, 플러그인 버전 또는 `filemtime()` 중 하나로 일관되게 관리합니다.
260
262
  - 사용자가 접근하지 못하는 화면에 자산을 enqueue하지 않습니다. 단, 자산 노출 자체가 민감한 정보를 포함하지 않는지도 별도로 검토합니다.
261
263
  - 최종 HTML에서 CDN, unpkg, jsDelivr, 외부 icon font를 요청하지 않습니다.
262
264
 
265
+ ### 3.4 첫 페인트 — 사이드바·헤더가 늦게 보이는 이유
266
+
267
+ `db-admin-shell`, `db-sidebar`, `db-page-header`는 Web Component입니다. `browser.iife.js`가
268
+ `customElements.define`하기 전까지는 브라우저가 빈 unknown element로 그립니다.
269
+
270
+ 바로 보이게 하려면 **플러그인에서 스켈레톤을 따로 만들 필요는 없습니다.** 패키지 helper가
271
+ runtime을 head에 넣고, CSS는 `:not(:defined)`인 `db-*`를 숨깁니다. 플러그인이 할 일은
272
+ 해당 화면에만 enqueue하는 것입니다.
273
+
274
+ ```php
275
+ designbase_wordpress_ui_enqueue([
276
+ 'handle' => 'myplugin-wordpress-ui',
277
+ 'base_url' => $base_url,
278
+ 'base_path' => $base_path,
279
+ 'version' => self::UI_VERSION,
280
+ // 기본값 false. footer로 옮기면 사이드바/헤더가 늦게 나타납니다.
281
+ // 'in_footer' => false,
282
+ ]);
283
+ ```
284
+
285
+ 직접 `wp_enqueue_script`를 쓸 때도 다섯 번째 인자를 `false`(head)로 둡니다.
286
+
287
+ ```php
288
+ wp_enqueue_script('myplugin-wordpress-ui-browser', $src, [], $version, false);
289
+ ```
290
+
291
+ 몇 초나 걸리는 경우는 보통 runtime이 footer에 있거나, 플러그인 번들이 wordpress-ui를
292
+ 감싼 채 defer/비동기로 늦게 실행되는 경우입니다. wordpress-ui는 별도 파일로 head에
293
+ 두고, 플러그인 JS만 footer에서 이벤트·REST를 붙이세요.
294
+
263
295
  ## 4. HTML/vanilla 적용
264
296
 
265
297
  WordPress 플러그인과 테마의 기본 선택지는 vanilla/PHP입니다. React가 없어도 동일한 Designbase 스타일과 ui-wc Web Component를 사용할 수 있습니다.
@@ -267,15 +299,16 @@ WordPress 플러그인과 테마의 기본 선택지는 vanilla/PHP입니다. Re
267
299
  ### 4.1 페이지 기본 구조
268
300
 
269
301
  PHP 템플릿은 `.designbase-wp-admin` root 안에서 `db-admin-shell`을 선언하는 방식을
270
- 권장합니다. 이 Web Component가 실제 `db-sidebar`, 플러그인명 브랜드,
302
+ 권장합니다. 이 Web Component가 실제 `db-sidebar`, 플러그인명 로고,
271
303
  `db-page-header`, 콘텐츠용 `<db-container size="full" padding="l" full-width>`를
272
- 하나의 패턴으로 렌더링합니다. 기존 템플릿을 단계적으로 이전하는 동안에는 화면별
273
- adapter가 같은 `db-admin-shell`을 생성하도록 사용할 수 있습니다.
304
+ 하나의 패턴으로 렌더링합니다.
305
+
306
+ `title`(또는 `brand`)은 사이드바 **헤더 로고**입니다. 메뉴는 `items` JSON으로 넘기고,
307
+ 링크·권한·활성 상태는 소비 플러그인이나 테마가 계산합니다. 메뉴를 실제 그룹으로 나눌
308
+ 때만 `sections`를 쓰고, 그룹 제목에 플러그인명을 넣지 않습니다.
274
309
 
275
- `sections`/`items`는 PHP에서 `wp_json_encode()`로 전달하고, 링크·권한·활성 상태는
276
- 소비 플러그인이나 테마가 관리합니다. 일반적인 화면은 아래처럼 `db-admin-shell` 하나를
277
- 선언하면 됩니다. 직접 자식 `db-page-header`는 헤더로 유지되고, 나머지 자식은 shell이
278
- `db-container` 안으로 이동합니다.
310
+ 직접 자식 `db-page-header`는 헤더로 유지되고, 나머지 자식은 shell이 `db-container`
311
+ 안으로 이동합니다.
279
312
 
280
313
  ```php
281
314
  <?php
@@ -284,7 +317,7 @@ $sidebar_items = [
284
317
  'id' => 'dashboard',
285
318
  'label' => __('대시보드', 'myplugin'),
286
319
  'href' => admin_url('admin.php?page=myplugin'),
287
- 'icon' => 'doughnut-chart',
320
+ 'icon' => 'dashboard',
288
321
  'active' => (($_GET['page'] ?? '') === 'myplugin'),
289
322
  ],
290
323
  [
@@ -299,21 +332,15 @@ $sidebar_items = [
299
332
  <div class="wrap designbase-wp-admin myplugin-admin">
300
333
  <db-admin-shell
301
334
  title="My Plugin"
302
- sections='<?php echo esc_attr(wp_json_encode([[
303
- 'id' => 'main',
304
- 'title' => 'My Plugin',
305
- 'items' => $sidebar_items,
306
- ]])); ?>'>
335
+ items="<?php echo esc_attr(wp_json_encode($sidebar_items)); ?>"
336
+ >
307
337
  <db-page-header
308
338
  title="<?php esc_attr_e('대시보드', 'myplugin'); ?>"
309
339
  description="<?php esc_attr_e('플러그인 상태와 최근 작업을 확인합니다.', 'myplugin'); ?>"
310
- variant="minimal"
311
- align="left">
312
- <div slot="actions">
313
- <a class="button button-secondary" href="<?php echo esc_url(admin_url('admin.php?page=myplugin-settings')); ?>">
314
- <?php esc_html_e('설정', 'myplugin'); ?>
315
- </a>
316
- </div>
340
+ variant="minimal">
341
+ <a slot="actions" class="button button-secondary" href="<?php echo esc_url(admin_url('admin.php?page=myplugin-settings')); ?>">
342
+ <?php esc_html_e('설정', 'myplugin'); ?>
343
+ </a>
317
344
  </db-page-header>
318
345
 
319
346
  <db-section title="<?php esc_attr_e('콘텐츠', 'myplugin'); ?>">
@@ -409,10 +436,10 @@ select?.addEventListener('db-change', (event) => {
409
436
  아이콘은 이모지나 임의의 유니코드 문자를 사용하지 않고 Designbase icons 이름을 사용합니다.
410
437
 
411
438
  ```html
412
- <i class="dbwp-admin-icon icon-dashboard" aria-hidden="true"></i>
413
- <i class="dbwp-admin-icon icon-file-manager" aria-hidden="true"></i>
414
- <i class="dbwp-admin-icon icon-search" aria-hidden="true"></i>
415
- <i class="dbwp-admin-icon icon-settings" aria-hidden="true"></i>
439
+ <i class="icon-dashboard" aria-hidden="true"></i>
440
+ <i class="icon-file-manager" aria-hidden="true"></i>
441
+ <i class="icon-search" aria-hidden="true"></i>
442
+ <i class="icon-settings" aria-hidden="true"></i>
416
443
  ```
417
444
 
418
445
  `styles.css`가 아이콘 폰트와 `@font-face` 규칙을 포함합니다. 아이콘이 보이지 않으면 다음을 확인합니다.
@@ -427,20 +454,21 @@ select?.addEventListener('db-change', (event) => {
427
454
  React는 선택 사항입니다. Gutenberg나 기존 React 앱과 연결해야 하는 화면에서만 사용하고, 일반적인 PHP admin page에는 vanilla entry를 권장합니다.
428
455
 
429
456
  ```bash
430
- npm install @designbasekorea/wordpress-ui@0.1.5 react react-dom
457
+ npm install @designbasekorea/wordpress-ui@0.1.7 react react-dom
431
458
  ```
432
459
 
433
460
  ```tsx
434
461
  import '@designbasekorea/wordpress-ui/styles.css';
435
462
  import {
436
- AdminDataTable,
437
- AdminEmptyState,
438
- AdminFilterBar,
439
463
  AdminPage,
440
464
  AdminPageContent,
441
465
  AdminPageHeader,
442
- AdminSection,
443
466
  AdminShell,
467
+ Button,
468
+ SearchBar,
469
+ Section,
470
+ Select,
471
+ Table,
444
472
  type AdminNavItem,
445
473
  } from '@designbasekorea/wordpress-ui/react';
446
474
 
@@ -451,59 +479,61 @@ const sidebarItems: AdminNavItem[] = [
451
479
 
452
480
  export function MyPluginAdmin() {
453
481
  return (
454
- <div className="designbase-wp-admin">
455
- <AdminShell sidebarItems={sidebarItems} sidebarTitle="My Plugin">
456
- <AdminPage>
457
- <AdminPageHeader
458
- title="콘텐츠 관리"
459
- icon="file-manager"
460
- description="콘텐츠를 검색하고 상태를 관리합니다."
461
- />
462
- <AdminPageContent maxWidth="xl">
463
- <AdminSection title="검색 및 필터">
464
- <AdminFilterBar
465
- searchPlaceholder="제목 검색"
466
- statusPlaceholder="전체 상태"
467
- statusOptions={[
468
- { value: 'all', label: '전체 상태' },
469
- { value: 'published', label: '공개' },
470
- { value: 'draft', label: '임시글' },
471
- ]}
472
- onSubmit={(event) => {
473
- event.preventDefault();
474
- // REST 또는 URL query 변경은 소비 앱이 담당한다.
475
- }}
476
- />
477
- </AdminSection>
478
- <AdminSection title="목록">
479
- <AdminDataTable
480
- columns={[
481
- { id: 'title', header: '제목', key: 'title', sortable: true },
482
- { id: 'status', header: '상태', key: 'status' },
483
- ]}
484
- rows={[]}
485
- emptyState={<AdminEmptyState title="콘텐츠가 없습니다." />}
486
- />
487
- </AdminSection>
488
- </AdminPageContent>
489
- </AdminPage>
490
- </AdminShell>
491
- </div>
482
+ <AdminShell sidebarItems={sidebarItems} sidebarTitle="My Plugin">
483
+ <AdminPageHeader
484
+ title="콘텐츠 관리"
485
+ description="콘텐츠를 검색하고 상태를 관리합니다."
486
+ actions={<Button variant="primary" size="s">새 페이지</Button>}
487
+ />
488
+ <AdminPage>
489
+ <AdminPageContent>
490
+ <Section title="검색 및 필터">
491
+ <form
492
+ className="designbase-wp-admin__filter-bar"
493
+ role="search"
494
+ onSubmit={(event) => {
495
+ event.preventDefault();
496
+ // REST 또는 URL query 변경은 소비 앱이 담당한다.
497
+ }}
498
+ >
499
+ <div className="designbase-wp-admin__filter-bar-toolbar">
500
+ <SearchBar name="search" placeholder="제목 검색" aria-label="제목 검색" />
501
+ <Select
502
+ name="status"
503
+ aria-label="상태"
504
+ options={JSON.stringify([
505
+ { value: 'all', label: '전체 상태' },
506
+ { value: 'published', label: '공개' },
507
+ { value: 'draft', label: '임시글' },
508
+ ])}
509
+ />
510
+ </div>
511
+ </form>
512
+ </Section>
513
+ <Section title="목록" fullWidth>
514
+ <Table
515
+ columns={JSON.stringify([
516
+ { key: 'title', header: '제목', sortable: true },
517
+ { key: 'status', header: '상태' },
518
+ ])}
519
+ data={JSON.stringify([])}
520
+ rowKey="id"
521
+ emptyMessage="콘텐츠가 없습니다."
522
+ />
523
+ </Section>
524
+ </AdminPageContent>
525
+ </AdminPage>
526
+ </AdminShell>
492
527
  );
493
528
  }
494
529
  ```
495
530
 
496
- React adapter의 책임은 관리자 shell과 컴포넌트 조합입니다.
531
+ React adapter의 책임은 관리자 shell과 ui-wc primitives 조합입니다.
497
532
 
498
- - `AdminShell`: 내부 sidebar와 main layout
499
- - `AdminSidebar`: 메뉴, active 상태, badge, 모바일 close
533
+ - `AdminShell`: `sidebarTitle`(사이드바 로고)과 `sidebarItems`(메뉴). 내부에서 `.designbase-wp-admin` root를 만듭니다.
500
534
  - `AdminPage`, `AdminPageContent`: 페이지 폭과 밀도
501
- - `AdminPageHeader`: title, icon, description, breadcrumb, action, back link
502
- - `AdminSection`: 제목, 설명, action, optional collapse
503
- - `AdminFilterBar`: 검색과 상태 필터 표현
504
- - `AdminTabs`: 탭 표현과 active 상태
505
- - `AdminDataTable`: column, row, sort, loading, empty, error 상태 표현
506
- - `AdminEmptyState`, `AdminLoadingState`, `AdminErrorState`: 상태 화면
535
+ - `AdminPageHeader`: title, description, breadcrumb, action. 모바일에서는 메뉴 버튼을 붙입니다.
536
+ - `Section`, `Table`, `SearchBar`, `Select`, `Tabs`, `EmptyState`, `Modal` 등: 같은 패키지의 React primitives. `AdminSection` / `AdminDataTable` / `AdminFilterBar` 같은 별도 래퍼는 없습니다.
507
537
 
508
538
  이 컴포넌트들은 REST 요청, 페이지네이션 API, nonce 갱신, capability 검사를 대신하지 않습니다. React state와 서버 데이터의 생명주기는 플러그인/테마 앱이 소유합니다.
509
539
 
@@ -638,14 +668,14 @@ register_setting('myplugin', 'myplugin_options', [
638
668
  ```text
639
669
  .designbase-wp-admin
640
670
  └─ AdminShell 또는 db-admin-shell
641
- ├─ AdminSidebar 또는 plugin 내부 nav
671
+ ├─ db-sidebar (title/sidebarTitle = 플러그인명 로고, items = 메뉴)
642
672
  └─ main
643
673
  ├─ AdminPageHeader / db-page-header
644
- ├─ AdminTabs / db-tabs (필요한 경우)
674
+ ├─ Tabs / db-tabs (필요한 경우)
645
675
  └─ AdminPageContent
646
- ├─ AdminSection / db-section
647
- ├─ AdminFilterBar
648
- └─ AdminDataTable 또는 native table
676
+ ├─ Section / db-section
677
+ ├─ form.designbase-wp-admin__filter-bar
678
+ └─ Table / db-table 또는 native table
649
679
  ```
650
680
 
651
681
  ### 7.1 페이지 헤더
@@ -660,7 +690,7 @@ register_setting('myplugin', 'myplugin_options', [
660
690
 
661
691
  ### 7.2 section
662
692
 
663
- 서로 다른 목적의 콘텐츠를 하나의 큰 카드에 몰아넣지 않습니다. 제목·설명·action이 있는 `AdminSection` 또는 `db-section`으로 묶습니다. 접기 상태를 제공할 때에는 키보드로 열고 닫을 수 있어야 하며, 기본 상태는 콘텐츠 중요도에 따라 결정합니다.
693
+ 서로 다른 목적의 콘텐츠를 하나의 큰 카드에 몰아넣지 않습니다. 제목·설명·action이 있는 `Section` 또는 `db-section`으로 묶습니다. 접기 상태를 제공할 때에는 키보드로 열고 닫을 수 있어야 하며, 기본 상태는 콘텐츠 중요도에 따라 결정합니다.
664
694
 
665
695
  ### 7.3 filter bar
666
696
 
@@ -674,13 +704,13 @@ register_setting('myplugin', 'myplugin_options', [
674
704
 
675
705
  ### 7.4 data table
676
706
 
677
- 단순한 표는 native `<table>`을 우선 사용합니다. 정렬·행 action·empty/loading/error가 반복되거나 React 데이터 모델을 사용하는 경우 `AdminDataTable` 또는 `db-table`을 사용합니다.
707
+ 단순한 표는 native `<table>`을 우선 사용합니다. 정렬·행 action·empty/loading/error가 반복되거나 React 데이터 모델을 사용하는 경우 `Table` 또는 `db-table`을 사용합니다.
678
708
 
679
709
  - 열 제목을 `<th>`로 출력합니다.
680
710
  - 행 action은 명확한 accessible name을 사용합니다.
681
711
  - 정렬 방향은 텍스트나 `aria-sort`로 전달합니다.
682
712
  - 로딩 중 기존 데이터가 있으면 전체 레이아웃을 깜빡이지 않고 해당 영역만 busy로 표시합니다.
683
- - 데이터가 없을 때 빈 `<table>`만 보여주지 말고 `AdminEmptyState`를 제공합니다.
713
+ - 데이터가 없을 때 빈 `<table>`만 보여주지 말고 `empty-message` 또는 `EmptyState` / `db-empty-state`를 제공합니다.
684
714
  - 삭제·상태 변경 action은 서버 응답이 성공한 뒤 목록을 갱신합니다.
685
715
 
686
716
  ## 8. 상태 표현과 오류 처리
@@ -689,9 +719,9 @@ register_setting('myplugin', 'myplugin_options', [
689
719
 
690
720
  | 상태 | 사용자에게 보여줄 것 | 권장 구현 |
691
721
  | --- | --- | --- |
692
- | loading | 작업 중임과 예상 영역 | `AdminLoadingState`, `db-spinner`, `db-skeleton` |
693
- | empty | 결과가 없다는 설명과 다음 action | `AdminEmptyState`, `db-empty-state` |
694
- | error | 문제와 재시도 방법 | `AdminErrorState`, `db-alert` |
722
+ | loading | 작업 중임과 예상 영역 | `Spinner` / `db-spinner`, `Skeleton` / `db-skeleton` |
723
+ | empty | 결과가 없다는 설명과 다음 action | `EmptyState` / `db-empty-state`, `db-table`의 `empty-message` |
724
+ | error | 문제와 재시도 방법 | `Alert` / `db-alert` |
695
725
  | success | 저장·삭제 완료 피드백 | toast + 변경된 영역 갱신 |
696
726
  | unauthorized | 권한 부족 안내 | 서버의 403/WordPress 권한 화면과 일치 |
697
727
 
@@ -782,7 +812,7 @@ body { ... }
782
812
 
783
813
  - input/select/button이 브라우저 기본 모양으로 보임: `styles.css`가 빠졌거나 root 밖에 렌더링된 경우가 많습니다.
784
814
  - 아이콘이 네모 또는 빈 공간으로 보임: font 파일 경로, CSS font-family, 배포 파일 누락을 확인합니다.
785
- - `db-*` element가 평범한 빈 element처럼 보임: `browser.iife.js`가 로드되지 않았거나 custom element 등록 전에 markup이 실행된 경우입니다.
815
+ - `db-*` element가 평범한 빈 element처럼 보였다가 늦게 채워짐: `browser.iife.js`가 footer/`defer`로 로드되고 있을 가능성이 큽니다. helper 기본값(head)을 쓰거나 `in_footer => false`인지 확인합니다.
786
816
  - WordPress 다른 화면까지 모양이 바뀜: root 밖의 전역 selector가 존재하는지 확인합니다.
787
817
  - sidebar 모바일 toggle이 작동하지 않음: `data-dbwp-sidebar-toggle` 대상 ID, browser runtime, `aria-expanded`를 확인합니다.
788
818
 
@@ -794,9 +824,9 @@ body { ... }
794
824
  2. 화면 root에 `.designbase-wp-admin`을 추가합니다.
795
825
  3. 해당 화면에만 `styles.css`와 `browser.iife.js`를 enqueue합니다.
796
826
  4. 기존 페이지 header/content 영역을 `AdminPageHeader` 또는 `db-page-header` 구조로 바꿉니다.
797
- 5. 반복되는 section을 `AdminSection` 또는 `db-section`으로 정리합니다.
798
- 6. 검색·필터 화면에 `AdminFilterBar` 또는 native-first filter markup을 적용합니다.
799
- 7. 목록 화면에 `AdminDataTable` 또는 semantic native table을 적용합니다.
827
+ 5. 반복되는 section을 `Section` 또는 `db-section`으로 정리합니다.
828
+ 6. 검색·필터 화면에 `form.designbase-wp-admin__filter-bar`와 `SearchBar`/`db-search-bar`를 적용합니다.
829
+ 7. 목록 화면에 `Table`/`db-table` 또는 semantic native table을 적용합니다.
800
830
  8. loading·empty·error·success 상태를 분리합니다.
801
831
  9. modal, confirm, toast, drawer를 필요한 화면에만 추가합니다.
802
832
  10. REST·AJAX·Settings API·capability 동작은 UI migration 중 변경하지 않고 회귀 테스트합니다.
@@ -898,7 +928,7 @@ import '@designbasekorea/wordpress-ui/browser';
898
928
  import '@designbasekorea/wordpress-ui/styles.css';
899
929
 
900
930
  // React 화면에서만 허용
901
- import { AdminShell, AdminDataTable } from '@designbasekorea/wordpress-ui/react';
931
+ import { AdminShell, Table } from '@designbasekorea/wordpress-ui/react';
902
932
  import { DbButton, DbInput, DbSelect, DbModal } from '@designbasekorea/wordpress-ui/components';
903
933
  // 또는: import { DbButton, DbInput, DbSelect, DbModal } from '@designbasekorea/wordpress-ui';
904
934
 
@@ -5,13 +5,14 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1">
6
6
  <title>wordpress-ui vanilla example</title>
7
7
  <link rel="stylesheet" href="../dist/styles.css">
8
+ <script src="../dist/browser.iife.js"></script>
8
9
  </head>
9
10
  <body>
10
11
  <div class="wrap designbase-wp-admin">
11
12
  <db-admin-shell
12
13
  id="wordpress-ui-example-shell"
13
14
  title="PageNest"
14
- sections='[{"id":"main","title":"PageNest","items":[{"id":"dashboard","label":"대시보드","href":"#dashboard","icon":"dashboard","active":true},{"id":"pages","label":"페이지 목록","href":"#pages","icon":"file-manager","badge":12},{"id":"settings","label":"설정","href":"#settings","icon":"settings"}]}]'
15
+ items='[{"id":"dashboard","label":"대시보드","href":"#dashboard","icon":"dashboard","active":true},{"id":"pages","label":"페이지 목록","href":"#pages","icon":"file-manager","badge":12},{"id":"settings","label":"설정","href":"#settings","icon":"settings"}]'
15
16
  >
16
17
  <db-page-header
17
18
  title="페이지 목록"
@@ -53,6 +54,5 @@
53
54
  </db-section>
54
55
  </db-admin-shell>
55
56
  </div>
56
- <script src="../dist/browser.iife.js"></script>
57
57
  </body>
58
58
  </html>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@designbasekorea/wordpress-ui",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "WordPress 관리자용 Designbase UI primitives와 plugin shell patterns",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -74,7 +74,7 @@
74
74
  "build-storybook": "storybook build"
75
75
  },
76
76
  "dependencies": {
77
- "@designbasekorea/ui-wc": "0.8.6"
77
+ "@designbasekorea/ui-wc": "0.8.7"
78
78
  },
79
79
  "peerDependencies": {
80
80
  "react": ">=18.0.0 <20.0.0",
package/wordpress-ui.php CHANGED
@@ -19,6 +19,9 @@ if (!function_exists('designbase_wordpress_ui_enqueue')) {
19
19
  * @type string $base_url Public URL of the package root.
20
20
  * @type string $base_path Filesystem path of the package root.
21
21
  * @type string $version Optional cache version.
22
+ * @type bool $in_footer When true, print the runtime in the footer.
23
+ * Default false so custom elements upgrade before
24
+ * plugin markup is parsed (avoids empty sidebar/header).
22
25
  * }
23
26
  * @return bool
24
27
  */
@@ -33,6 +36,7 @@ if (!function_exists('designbase_wordpress_ui_enqueue')) {
33
36
  'base_url' => '',
34
37
  'base_path' => '',
35
38
  'version' => '',
39
+ 'in_footer' => false,
36
40
  ]);
37
41
 
38
42
  $base_url = untrailingslashit((string) $args['base_url']);
@@ -58,7 +62,13 @@ if (!function_exists('designbase_wordpress_ui_enqueue')) {
58
62
  }
59
63
 
60
64
  wp_enqueue_style($handle, $base_url . '/dist/styles.css', [], $version);
61
- wp_enqueue_script($handle . '-browser', $base_url . '/dist/browser.iife.js', [], $version, true);
65
+ wp_enqueue_script(
66
+ $handle . '-browser',
67
+ $base_url . '/dist/browser.iife.js',
68
+ [],
69
+ $version,
70
+ !empty($args['in_footer'])
71
+ );
62
72
 
63
73
  return true;
64
74
  }