@gemafajarramadhan/dynamic-ui 1.0.4 → 1.0.6

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/README.md CHANGED
@@ -8,11 +8,18 @@ Library **Vue 3** component yang bisa digunakan di berbagai framework (Vue, Reac
8
8
 
9
9
  - [Fitur](#fitur)
10
10
  - [Instalasi](#instalasi)
11
+ - [⚡ Konfigurasi API (WAJIB)](#-konfigurasi-api-wajib)
12
+ - [Vue 3](#konfigurasi-api-di-vue-3)
13
+ - [Nuxt 3](#konfigurasi-api-di-nuxt-3)
14
+ - [React / Next.js](#konfigurasi-api-di-react--nextjs)
15
+ - [Angular](#konfigurasi-api-di-angular)
16
+ - [Vanilla JS (window global)](#konfigurasi-api-via-window-global)
11
17
  - [Komponen Base (Vue Components)](#komponen-base-vue-components)
12
18
  - [Daftar Komponen](#daftar-komponen)
13
19
  - [Penggunaan di Vue 3 (Import Per Komponen)](#penggunaan-di-vue-3-import-per-komponen)
14
20
  - [Penggunaan di Vue 3 (Global Plugin)](#penggunaan-di-vue-3-global-plugin)
15
21
  - [Penggunaan di Nuxt 3](#penggunaan-di-nuxt-3-vue-components)
22
+ - [DCodeAutoComplete – Komponen dengan API](#dcodeautocomplete--komponen-dengan-api)
16
23
  - [Web Components (Framework Agnostic)](#web-components-framework-agnostic)
17
24
  - [API Referensi Web Components](#api-referensi-web-components)
18
25
  - [Logic Registry API](#logic-registry-api)
@@ -36,6 +43,7 @@ Library **Vue 3** component yang bisa digunakan di berbagai framework (Vue, Reac
36
43
  - 🔌 **Logic Registry** – Daftarkan custom business logic dari aplikasi host tanpa perlu memodifikasi library.
37
44
  - 🎨 **Style Bundled** – CSS sudah ter-bundle, cukup import satu file style.
38
45
  - 🌐 **i18n Ready** – Mendukung internasionalisasi (vue-i18n).
46
+ - 🔐 **API Config** – Base URL dan auth token diambil dari **host project**, bukan dari env package ini.
39
47
 
40
48
  ---
41
49
 
@@ -54,6 +62,173 @@ pnpm add @gemafajarramadhan/dynamic-ui
54
62
 
55
63
  ---
56
64
 
65
+ ## ⚡ Konfigurasi API (WAJIB)
66
+
67
+ > **Penting:** Komponen seperti `DCodeAutoComplete` melakukan HTTP request ke API. Base URL dan auth token **diambil dari host project**, bukan dari `.env` package ini. Anda **wajib** mengkonfigurasi ini di aplikasi host sebelum menggunakan komponen.
68
+
69
+ Library menggunakan sistem konfigurasi terpusat via `setApiConfig()` (atau via Vue Plugin). Berikut urutan prioritas resolusi base URL:
70
+
71
+ | Prioritas | Sumber |
72
+ |-----------|--------|
73
+ | 1️⃣ Tertinggi | `apiBaseUrl` via plugin / `setApiConfig()` |
74
+ | 2️⃣ | `window.__MICRO_API_BASE_URL__` (global) |
75
+ | 3️⃣ | `import.meta.env.VITE_API_BASE_URL` (env host) |
76
+ | 4️⃣ Terendah | `''` (same-origin fallback) |
77
+
78
+ ---
79
+
80
+ ### Konfigurasi API di Vue 3
81
+
82
+ Cara paling direkomendasikan: lewatkan config saat `app.use()`.
83
+
84
+ ```js
85
+ // main.js
86
+ import { createApp } from 'vue'
87
+ import App from './App.vue'
88
+ import DynamicUI from '@gemafajarramadhan/dynamic-ui'
89
+ import '@gemafajarramadhan/dynamic-ui/style.css'
90
+
91
+ const app = createApp(App)
92
+
93
+ app.use(DynamicUI, {
94
+ // ✅ Base URL API dari env HOST project
95
+ apiBaseUrl: import.meta.env.VITE_API_BASE_URL,
96
+
97
+ // ✅ Token auth terkini (dipanggil setiap request)
98
+ getAuthToken: () => localStorage.getItem('access_token'),
99
+
100
+ // ✅ Atau gunakan custom headers penuh (override Authorization)
101
+ // getHeaders: () => ({
102
+ // Authorization: `Bearer ${store.getters.token}`,
103
+ // 'X-App-ID': 'my-app',
104
+ // }),
105
+
106
+ // ✅ Callback ketika response 401 (Unauthorized)
107
+ onUnauthorized: () => {
108
+ router.push('/login')
109
+ },
110
+ })
111
+
112
+ app.mount('#app')
113
+ ```
114
+
115
+ > File `.env` di host project Anda:
116
+ > ```env
117
+ > VITE_API_BASE_URL=https://api.example.com
118
+ > ```
119
+
120
+ ---
121
+
122
+ ### Konfigurasi API di Nuxt 3
123
+
124
+ ```ts
125
+ // plugins/dynamic-ui.ts
126
+ import DynamicUI from '@gemafajarramadhan/dynamic-ui'
127
+ import '@gemafajarramadhan/dynamic-ui/style.css'
128
+
129
+ export default defineNuxtPlugin((nuxtApp) => {
130
+ const config = useRuntimeConfig()
131
+
132
+ nuxtApp.vueApp.use(DynamicUI, {
133
+ // Ambil dari runtimeConfig Nuxt
134
+ apiBaseUrl: config.public.apiBaseUrl,
135
+
136
+ getAuthToken: () => useCookie('access_token').value ?? null,
137
+
138
+ onUnauthorized: () => {
139
+ navigateTo('/login')
140
+ },
141
+ })
142
+ })
143
+ ```
144
+
145
+ > File `nuxt.config.ts` di host project:
146
+ > ```ts
147
+ > export default defineNuxtConfig({
148
+ > runtimeConfig: {
149
+ > public: {
150
+ > apiBaseUrl: process.env.VITE_API_BASE_URL, // set di .env
151
+ > },
152
+ > },
153
+ > })
154
+ > ```
155
+
156
+ ---
157
+
158
+ ### Konfigurasi API di React / Next.js
159
+
160
+ Gunakan fungsi `setApiConfig()` secara langsung (tidak perlu Vue plugin).
161
+
162
+ ```ts
163
+ // src/lib/dynamic-ui-config.ts (jalankan sebelum render app)
164
+ import { setApiConfig } from '@gemafajarramadhan/dynamic-ui'
165
+
166
+ setApiConfig({
167
+ apiBaseUrl: process.env.NEXT_PUBLIC_API_BASE_URL,
168
+
169
+ getAuthToken: () => localStorage.getItem('access_token'),
170
+
171
+ onUnauthorized: () => {
172
+ window.location.href = '/login'
173
+ },
174
+ })
175
+ ```
176
+
177
+ Panggil di entry point:
178
+
179
+ ```tsx
180
+ // app/layout.tsx atau _app.tsx
181
+ 'use client'
182
+ import '@/lib/dynamic-ui-config' // ← jalankan konfigurasi lebih dulu
183
+ import '@gemafajarramadhan/dynamic-ui/style.css'
184
+ ```
185
+
186
+ > File `.env.local` di host project Next.js:
187
+ > ```env
188
+ > NEXT_PUBLIC_API_BASE_URL=https://api.example.com
189
+ > ```
190
+
191
+ ---
192
+
193
+ ### Konfigurasi API di Angular
194
+
195
+ ```ts
196
+ // main.ts
197
+ import { setApiConfig } from '@gemafajarramadhan/dynamic-ui'
198
+ import '@gemafajarramadhan/dynamic-ui'
199
+ import '@gemafajarramadhan/dynamic-ui/style.css'
200
+
201
+ // Konfigurasi sebelum bootstrap
202
+ setApiConfig({
203
+ apiBaseUrl: (window as any).__env?.API_BASE_URL || 'https://api.example.com',
204
+
205
+ getAuthToken: () => localStorage.getItem('access_token'),
206
+
207
+ onUnauthorized: () => {
208
+ window.location.href = '/login'
209
+ },
210
+ })
211
+
212
+ platformBrowserDynamic().bootstrapModule(AppModule)
213
+ ```
214
+
215
+ ---
216
+
217
+ ### Konfigurasi API via Window Global
218
+
219
+ Alternatif tanpa import fungsi – set sebelum library dimuat:
220
+
221
+ ```html
222
+ <script>
223
+ // Set sebelum import library
224
+ window.__MICRO_API_BASE_URL__ = 'https://api.example.com'
225
+ window.__MICRO_AUTH_TOKEN__ = 'your-auth-token' // atau ambil dari cookie/localStorage
226
+ </script>
227
+ <script type="module" src="./main.js"></script>
228
+ ```
229
+
230
+ ---
231
+
57
232
  ## Komponen Base (Vue Components)
58
233
 
59
234
  Selain Web Components, library ini juga menyediakan **27 komponen Vue** yang bisa digunakan langsung di aplikasi Vue 3, Nuxt 3, dan framework apapun yang mendukung Vue.
@@ -70,7 +245,7 @@ Selain Web Components, library ini juga menyediakan **27 komponen Vue** yang bis
70
245
  | `DCodeSwitch` | Toggle switch |
71
246
  | `DCodeRadioCustom` | Radio button dengan opsi kustom |
72
247
  | `DCodeLabel` | Label untuk form |
73
- | `DCodeAutoComplete` | Input autocomplete dengan pencarian |
248
+ | `DCodeAutoComplete` | Input autocomplete dengan pencarian dan fetch API otomatis |
74
249
  | `DCodeMultiSelect` | Dropdown multi-pilihan |
75
250
  | `DCodeDatePicker` | Date picker kalender |
76
251
  | `DCodeDateRangePicker` | Date range picker |
@@ -96,10 +271,6 @@ Selain Web Components, library ini juga menyediakan **27 komponen Vue** yang bis
96
271
 
97
272
  Cara paling ringan: import hanya komponen yang diperlukan.
98
273
 
99
- ```bash
100
- npm install @gemafajarramadhan/dynamic-ui
101
- ```
102
-
103
274
  ```vue
104
275
  <!-- MyForm.vue -->
105
276
  <script setup>
@@ -153,7 +324,12 @@ import DynamicUI from '@gemafajarramadhan/dynamic-ui'
153
324
  import '@gemafajarramadhan/dynamic-ui/style.css'
154
325
 
155
326
  const app = createApp(App)
156
- app.use(DynamicUI) // Mendaftarkan semua DCode* komponen secara global
327
+
328
+ app.use(DynamicUI, {
329
+ apiBaseUrl: import.meta.env.VITE_API_BASE_URL,
330
+ getAuthToken: () => localStorage.getItem('access_token'),
331
+ })
332
+
157
333
  app.mount('#app')
158
334
  ```
159
335
 
@@ -180,7 +356,12 @@ import DynamicUI from '@gemafajarramadhan/dynamic-ui'
180
356
  import '@gemafajarramadhan/dynamic-ui/style.css'
181
357
 
182
358
  export default defineNuxtPlugin((nuxtApp) => {
183
- nuxtApp.vueApp.use(DynamicUI)
359
+ const config = useRuntimeConfig()
360
+
361
+ nuxtApp.vueApp.use(DynamicUI, {
362
+ apiBaseUrl: config.public.apiBaseUrl,
363
+ getAuthToken: () => useCookie('access_token').value ?? null,
364
+ })
184
365
  })
185
366
  ```
186
367
 
@@ -198,6 +379,158 @@ Kemudian gunakan di page atau component manapun:
198
379
 
199
380
  ---
200
381
 
382
+ ## DCodeAutoComplete – Komponen dengan API
383
+
384
+ `DCodeAutoComplete` adalah komponen autocomplete yang bisa **langsung fetch data dari API** menggunakan konfigurasi yang sudah di-set di host project.
385
+
386
+ > ⚠️ Pastikan sudah mengatur [Konfigurasi API](#-konfigurasi-api-wajib) sebelum menggunakan fitur endpoint.
387
+
388
+ ### Perilaku Default
389
+
390
+ - Setiap fetch otomatis mengirimkan `page=1` dan `perPage=100` sebagai query parameter default.
391
+ - Nilai ini bisa di-override via prop `apiParams`.
392
+
393
+ ### Props Utama
394
+
395
+ | Prop | Tipe | Default | Deskripsi |
396
+ |------|------|---------|-----------|
397
+ | `modelValue` | `any` | — | Value terpilih (v-model) |
398
+ | `endpoint.apiUrl` | `string` | — | URL endpoint API (path atau full URL) |
399
+ | `endpoint.apiMethod` | `string` | `'GET'` | HTTP method |
400
+ | `apiParams` | `object` | `{}` | Query params tambahan (di-merge & bisa override default) |
401
+ | `itemTitle` | `string\|Function` | `'name'` | Field nama tampilan dari tiap item |
402
+ | `itemValue` | `string\|Function` | `'id'` | Field nilai dari tiap item |
403
+ | `returnObject` | `boolean` | `false` | Jika `true`, v-model menyimpan objek penuh, bukan hanya `id` |
404
+ | `clearable` | `boolean` | `false` | Tampilkan tombol hapus pilihan |
405
+ | `disabled` | `boolean` | `false` | Nonaktifkan komponen |
406
+ | `autoFetchOnOpen` | `boolean` | `true` | Fetch otomatis saat dropdown dibuka pertama kali |
407
+ | `autoFetchOnMount` | `boolean` | `false` | Fetch otomatis saat komponen pertama kali di-mount |
408
+
409
+ ### Contoh Penggunaan
410
+
411
+ #### Fetch dari API dengan URL langsung
412
+
413
+ ```vue
414
+ <template>
415
+ <DCodeAutoComplete
416
+ v-model="selectedId"
417
+ label="Pilih Departemen"
418
+ :endpoint="{ apiUrl: '/api/master/departemen', apiMethod: 'GET' }"
419
+ item-title="nama"
420
+ item-value="id"
421
+ clearable
422
+ />
423
+ </template>
424
+ ```
425
+
426
+ > Request yang dikirim: `GET /api/master/departemen?page=1&perPage=100`
427
+ > Base URL diambil otomatis dari konfigurasi host project (`apiBaseUrl`).
428
+
429
+ #### Dengan Parameter Tambahan
430
+
431
+ ```vue
432
+ <template>
433
+ <DCodeAutoComplete
434
+ v-model="selectedId"
435
+ label="Pilih Jabatan"
436
+ :endpoint="{ apiUrl: '/api/master/jabatan' }"
437
+ :apiParams="{ idDepartemen: selectedDeptId, isActive: true }"
438
+ item-title="namaJabatan"
439
+ item-value="idJabatan"
440
+ />
441
+ </template>
442
+ ```
443
+
444
+ > Request yang dikirim: `GET /api/master/jabatan?page=1&perPage=100&idDepartemen=5&isActive=true`
445
+
446
+ #### Override Default Pagination
447
+
448
+ ```vue
449
+ <template>
450
+ <!-- Ganti perPage menjadi 50 -->
451
+ <DCodeAutoComplete
452
+ v-model="selected"
453
+ label="Pilih Data"
454
+ :endpoint="{ apiUrl: '/api/data' }"
455
+ :apiParams="{ perPage: 50 }"
456
+ item-title="nama"
457
+ item-value="id"
458
+ />
459
+ </template>
460
+ ```
461
+
462
+ #### Dengan Data Statis (tanpa API)
463
+
464
+ ```vue
465
+ <template>
466
+ <DCodeAutoComplete
467
+ v-model="selected"
468
+ label="Pilih Status"
469
+ :items="[
470
+ { id: 1, name: 'Aktif' },
471
+ { id: 0, name: 'Nonaktif' },
472
+ ]"
473
+ item-title="name"
474
+ item-value="id"
475
+ />
476
+ </template>
477
+ ```
478
+
479
+ #### Return Object Penuh
480
+
481
+ ```vue
482
+ <script setup>
483
+ import { ref } from 'vue'
484
+
485
+ const selectedUser = ref(null) // akan berisi { id: 1, name: 'John', email: '...' }
486
+ </script>
487
+
488
+ <template>
489
+ <DCodeAutoComplete
490
+ v-model="selectedUser"
491
+ label="Pilih User"
492
+ :endpoint="{ apiUrl: '/api/users' }"
493
+ item-title="name"
494
+ item-value="id"
495
+ return-object
496
+ />
497
+ </template>
498
+ ```
499
+
500
+ ### Format Response API yang Diharapkan
501
+
502
+ ```json
503
+ {
504
+ "status": true,
505
+ "data": {
506
+ "data": [
507
+ { "id": 1, "name": "Item A" },
508
+ { "id": 2, "name": "Item B" }
509
+ ]
510
+ }
511
+ }
512
+ ```
513
+
514
+ Atau format flat:
515
+
516
+ ```json
517
+ {
518
+ "data": [
519
+ { "id": 1, "name": "Item A" }
520
+ ]
521
+ }
522
+ ```
523
+
524
+ Atau array langsung:
525
+
526
+ ```json
527
+ [
528
+ { "id": 1, "name": "Item A" }
529
+ ]
530
+ ```
531
+
532
+ ---
533
+
201
534
  ## Web Components (Framework Agnostic)
202
535
 
203
536
  Untuk digunakan di **React, Angular, Svelte**, atau framework lainnya, gunakan mode Web Components.
@@ -252,13 +585,13 @@ import {
252
585
 
253
586
  ---
254
587
 
255
- ## Cara Penggunaan
588
+ ## Penggunaan di Berbagai Framework
256
589
 
257
590
  ---
258
591
 
259
592
  ### 1. Vanilla HTML / JavaScript
260
593
 
261
- Cara paling sederhana. Import library dari CDN atau bundler, lalu gunakan custom element di HTML.
594
+ Cara paling sederhana. Import library dari bundler, lalu gunakan custom element di HTML.
262
595
 
263
596
  ```html
264
597
  <!DOCTYPE html>
@@ -279,10 +612,17 @@ Cara paling sederhana. Import library dari CDN atau bundler, lalu gunakan custom
279
612
 
280
613
  <!-- Import library (registrasi Web Components otomatis) -->
281
614
  <script type="module">
282
- import '@gemafajarramadhan/dynamic-ui';
615
+ import '@gemafajarramadhan/dynamic-ui'
616
+ import { setApiConfig } from '@gemafajarramadhan/dynamic-ui'
617
+
618
+ // ✅ Konfigurasi API dari host project
619
+ setApiConfig({
620
+ apiBaseUrl: 'https://api.example.com',
621
+ getAuthToken: () => localStorage.getItem('access_token'),
622
+ })
283
623
 
284
624
  // --- Setup Form ---
285
- const form = document.querySelector('#myForm');
625
+ const form = document.querySelector('#myForm')
286
626
  form.config = {
287
627
  title: 'Registrasi User',
288
628
  sections: [
@@ -306,25 +646,25 @@ Cara paling sederhana. Import library dari CDN atau bundler, lalu gunakan custom
306
646
  },
307
647
  ],
308
648
  actions: [{ key: 'submit', label: 'Daftar', component: 'DCodeButton' }],
309
- };
649
+ }
310
650
 
311
651
  form.addEventListener('submit', (e) => {
312
- console.log('Data Form:', e.detail);
313
- });
652
+ console.log('Data Form:', e.detail)
653
+ })
314
654
 
315
655
  // --- Setup DataTable ---
316
- const table = document.querySelector('#myTable');
656
+ const table = document.querySelector('#myTable')
317
657
  table.config = {
318
658
  titleID: 'Daftar User',
319
659
  headers: [
320
660
  { text: 'Nama', value: 'name' },
321
661
  { text: 'Email', value: 'email' },
322
662
  ],
323
- };
663
+ }
324
664
 
325
665
  table.addEventListener('action', (e) => {
326
- console.log('Action:', e.detail);
327
- });
666
+ console.log('Action:', e.detail)
667
+ })
328
668
  </script>
329
669
 
330
670
  </body>
@@ -333,7 +673,7 @@ Cara paling sederhana. Import library dari CDN atau bundler, lalu gunakan custom
333
673
 
334
674
  ---
335
675
 
336
- ### 2. Vue 3
676
+ ### 2. Vue 3 (Web Components)
337
677
 
338
678
  Di Vue 3, Web Components bisa dipakai langsung seperti HTML element biasa. Gunakan `ref` untuk set properti objek.
339
679
 
@@ -366,12 +706,19 @@ export default defineConfig({
366
706
  // main.js
367
707
  import { createApp } from 'vue'
368
708
  import App from './App.vue'
369
-
370
- // Import library (registrasi Web Components)
371
- import '@gemafajarramadhan/dynamic-ui'
709
+ import DynamicUI from '@gemafajarramadhan/dynamic-ui'
372
710
  import '@gemafajarramadhan/dynamic-ui/style.css'
373
711
 
374
- createApp(App).mount('#app')
712
+ const app = createApp(App)
713
+
714
+ // ✅ Konfigurasi API dari env host project
715
+ app.use(DynamicUI, {
716
+ apiBaseUrl: import.meta.env.VITE_API_BASE_URL,
717
+ getAuthToken: () => localStorage.getItem('access_token'),
718
+ onUnauthorized: () => router.push('/login'),
719
+ })
720
+
721
+ app.mount('#app')
375
722
  ```
376
723
 
377
724
  #### Komponen Vue (`MyForm.vue`)
@@ -429,11 +776,17 @@ Di React, gunakan `useRef` dan `useEffect` untuk set properti DOM secara imperat
429
776
  import React from 'react'
430
777
  import ReactDOM from 'react-dom/client'
431
778
  import App from './App'
432
-
433
- // Import library (registrasi Web Components)
779
+ import { setApiConfig } from '@gemafajarramadhan/dynamic-ui'
434
780
  import '@gemafajarramadhan/dynamic-ui'
435
781
  import '@gemafajarramadhan/dynamic-ui/style.css'
436
782
 
783
+ // ✅ Konfigurasi API dari env host project
784
+ setApiConfig({
785
+ apiBaseUrl: import.meta.env.VITE_API_BASE_URL,
786
+ getAuthToken: () => localStorage.getItem('access_token'),
787
+ onUnauthorized: () => { window.location.href = '/login' },
788
+ })
789
+
437
790
  ReactDOM.createRoot(document.getElementById('root')).render(<App />)
438
791
  ```
439
792
 
@@ -562,6 +915,19 @@ declare global {
562
915
 
563
916
  Di Next.js dengan App Router, Web Components harus di-import di sisi klien (`'use client'`).
564
917
 
918
+ #### Setup Konfigurasi API
919
+
920
+ ```ts
921
+ // lib/dynamic-ui-config.ts
922
+ import { setApiConfig } from '@gemafajarramadhan/dynamic-ui'
923
+
924
+ setApiConfig({
925
+ apiBaseUrl: process.env.NEXT_PUBLIC_API_BASE_URL!,
926
+ getAuthToken: () => localStorage.getItem('access_token'),
927
+ onUnauthorized: () => { window.location.href = '/login' },
928
+ })
929
+ ```
930
+
565
931
  #### Setup di Layout atau Client Component
566
932
 
567
933
  ```tsx
@@ -569,8 +935,7 @@ Di Next.js dengan App Router, Web Components harus di-import di sisi klien (`'us
569
935
  'use client'
570
936
 
571
937
  import { useEffect, useRef } from 'react'
572
-
573
- // Import hanya di sisi klien
938
+ import '@/lib/dynamic-ui-config'
574
939
  import('@gemafajarramadhan/dynamic-ui')
575
940
  import '@gemafajarramadhan/dynamic-ui/style.css'
576
941
 
@@ -639,6 +1004,11 @@ export default function HomePage() {
639
1004
  > const DynamicFormClient = dynamic(() => import('@/components/DynamicForm'), { ssr: false })
640
1005
  > ```
641
1006
 
1007
+ > File `.env.local` di host project:
1008
+ > ```env
1009
+ > NEXT_PUBLIC_API_BASE_URL=https://api.example.com
1010
+ > ```
1011
+
642
1012
  ---
643
1013
 
644
1014
  ### 5. Angular
@@ -666,16 +1036,30 @@ export class AppModule {}
666
1036
 
667
1037
  ```ts
668
1038
  // main.ts
669
- import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'
670
- import { AppModule } from './app/app.module'
671
-
672
- // Import library (registrasi Web Components)
1039
+ import { setApiConfig } from '@gemafajarramadhan/dynamic-ui'
673
1040
  import '@gemafajarramadhan/dynamic-ui'
674
1041
  import '@gemafajarramadhan/dynamic-ui/style.css'
675
1042
 
1043
+ // ✅ Konfigurasi API dari environment Angular
1044
+ import { environment } from './environments/environment'
1045
+
1046
+ setApiConfig({
1047
+ apiBaseUrl: environment.apiBaseUrl,
1048
+ getAuthToken: () => localStorage.getItem('access_token'),
1049
+ onUnauthorized: () => { window.location.href = '/login' },
1050
+ })
1051
+
676
1052
  platformBrowserDynamic().bootstrapModule(AppModule)
677
1053
  ```
678
1054
 
1055
+ > File `src/environments/environment.ts`:
1056
+ > ```ts
1057
+ > export const environment = {
1058
+ > production: false,
1059
+ > apiBaseUrl: 'https://api.example.com',
1060
+ > }
1061
+ > ```
1062
+
679
1063
  #### Komponen Angular (`dynamic-form.component.ts`)
680
1064
 
681
1065
  ```ts
@@ -761,11 +1145,18 @@ Buat file plugin dengan suffix `.client.ts` agar hanya dijalankan di sisi klien
761
1145
 
762
1146
  ```ts
763
1147
  // plugins/dynamic-ui.client.ts
764
- import '@gemafajarramadhan/dynamic-ui'
1148
+ import DynamicUI from '@gemafajarramadhan/dynamic-ui'
765
1149
  import '@gemafajarramadhan/dynamic-ui/style.css'
766
1150
 
767
- export default defineNuxtPlugin(() => {
768
- // Web Components sudah terdaftar saat import di atas
1151
+ export default defineNuxtPlugin((nuxtApp) => {
1152
+ const config = useRuntimeConfig()
1153
+
1154
+ // ✅ Konfigurasi API dari runtimeConfig Nuxt (env host project)
1155
+ nuxtApp.vueApp.use(DynamicUI, {
1156
+ apiBaseUrl: config.public.apiBaseUrl,
1157
+ getAuthToken: () => useCookie('access_token').value ?? null,
1158
+ onUnauthorized: () => navigateTo('/login'),
1159
+ })
769
1160
  })
770
1161
  ```
771
1162
 
@@ -774,6 +1165,11 @@ export default defineNuxtPlugin(() => {
774
1165
  ```ts
775
1166
  // nuxt.config.ts
776
1167
  export default defineNuxtConfig({
1168
+ runtimeConfig: {
1169
+ public: {
1170
+ apiBaseUrl: process.env.VITE_API_BASE_URL, // set di .env
1171
+ },
1172
+ },
777
1173
  vue: {
778
1174
  compilerOptions: {
779
1175
  // Arahkan Nuxt/Vue agar tidak menganggap element ini sebagai Vue component
@@ -912,6 +1308,8 @@ declare global {
912
1308
  // Untuk global window registry
913
1309
  interface Window {
914
1310
  __MICRO_LOGIC_REGISTRY__?: Record<string, DynamicUI.LogicModule>
1311
+ __MICRO_API_BASE_URL__?: string
1312
+ __MICRO_AUTH_TOKEN__?: string
915
1313
  }
916
1314
  }
917
1315