pgo-ui 1.0.78 → 1.0.80

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pgo-ui",
3
- "version": "1.0.78",
3
+ "version": "1.0.80",
4
4
  "description": "A Vue 3 component library with PGO design system",
5
5
  "private": false,
6
6
  "type": "module",
package/src/App.vue CHANGED
@@ -58,7 +58,7 @@
58
58
  <!-- ACTIONS -->
59
59
  <template #actions>
60
60
  <button class="p-2 rounded-full hover:bg-gray-100 dark:hover:bg-slate-700">
61
- <HeroIcon name="bell" size="22" class="text-black" />
61
+ <HeroIcon name="bell" size="22" color="text-current" />
62
62
  </button>
63
63
 
64
64
  <button class="hidden md:block p-2 rounded-full hover:bg-gray-100 dark:hover:bg-slate-700">
@@ -68,8 +68,8 @@
68
68
 
69
69
  <!-- APPEND -->
70
70
  <template #append>
71
- <button class="px-3 py-1 rounded-md bg-gray-600 text-white hover:bg-gray-700 cursor-pointer">
72
- <HeroIcon name="arrow-right-start-on-rectangle" size="22" />
71
+ <button class="p-2 rounded-md hover:bg-black/5 dark:hover:bg-white/10 cursor-pointer">
72
+ <HeroIcon name="arrow-right-start-on-rectangle" size="22" color="text-current" />
73
73
  </button>
74
74
  </template>
75
75
 
@@ -17,7 +17,7 @@
17
17
  densityClass,
18
18
  collapseClass
19
19
  ]"
20
- :style="[themeStyles, customStyle,]"
20
+ :style="[themeStyles, customStyle]"
21
21
  >
22
22
  <div
23
23
  :class="['w-full flex items-center justify-between', innerDirectionClass, dense ? 'h-12' : 'h-16']"
@@ -86,36 +86,48 @@
86
86
  </div>
87
87
  </div>
88
88
 
89
- <!-- Font Size Accessibility -->
90
- <div class="flex items-center">
91
- <button
92
- @click="onDecreaseFontScale"
93
- :disabled="fontScaleAtMin"
94
- class="px-1.5 py-1 rounded-md hover:bg-black/5 dark:hover:bg-white/10 cursor-pointer disabled:opacity-30 disabled:cursor-not-allowed"
95
- title="Decrease font size"
96
- >
97
- <span class="font-bold" style="font-size: 0.7rem;">A-</span>
98
- </button>
99
- <button
100
- @click="onResetFontScale"
101
- class="px-1 py-1 rounded-md hover:bg-black/5 dark:hover:bg-white/10 cursor-pointer"
102
- title="Reset font size"
103
- >
104
- <span style="font-size: 0.65rem;">{{ currentFontScale }}%</span>
89
+ <!-- Accessibility Menu -->
90
+ <div class="relative" ref="a11yMenuRef">
91
+ <button @click="toggleA11yMenu" class="p-2 rounded-md hover:bg-black/5 dark:hover:bg-white/10 cursor-pointer">
92
+ <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><circle cx="12" cy="7.5" r="1.5"/><path d="M8 11.5l4 1.333 4-1.333"/><path d="M12 12.833v1.5l-2 3"/><path d="M12 14.333l2 3"/></svg>
105
93
  </button>
106
- <button
107
- @click="onIncreaseFontScale"
108
- :disabled="fontScaleAtMax"
109
- class="px-1.5 py-1 rounded-md hover:bg-black/5 dark:hover:bg-white/10 cursor-pointer disabled:opacity-30 disabled:cursor-not-allowed"
110
- title="Increase font size"
94
+ <div
95
+ v-if="isA11yOpen"
96
+ :class="['absolute vts-mt-2 w-40 rounded shadow-lg z-50 p-3', overflowPositionClass]"
97
+ :style="{ backgroundColor: 'var(--vts-color-surfaceElevated)', borderColor: 'var(--vts-color-divider)' }"
111
98
  >
112
- <span class="font-bold" style="font-size: 0.85rem;">A+</span>
113
- </button>
99
+ <div class="text-xs opacity-60 mb-2">Font Size</div>
100
+ <div class="flex items-center justify-between">
101
+ <button
102
+ @click="onDecreaseFontScale"
103
+ :disabled="fontScaleAtMin"
104
+ class="px-1.5 py-1 rounded-md hover:bg-black/5 dark:hover:bg-white/10 cursor-pointer disabled:opacity-30 disabled:cursor-not-allowed"
105
+ title="Decrease font size"
106
+ >
107
+ <span class="font-bold" style="font-size: 0.7rem;">A-</span>
108
+ </button>
109
+ <button
110
+ @click="onResetFontScale"
111
+ class="px-1 py-1 rounded-md hover:bg-black/5 dark:hover:bg-white/10 cursor-pointer"
112
+ title="Reset font size"
113
+ >
114
+ <span style="font-size: 0.65rem;">{{ currentFontScale }}%</span>
115
+ </button>
116
+ <button
117
+ @click="onIncreaseFontScale"
118
+ :disabled="fontScaleAtMax"
119
+ class="px-1.5 py-1 rounded-md hover:bg-black/5 dark:hover:bg-white/10 cursor-pointer disabled:opacity-30 disabled:cursor-not-allowed"
120
+ title="Increase font size"
121
+ >
122
+ <span class="font-bold" style="font-size: 0.85rem;">A+</span>
123
+ </button>
124
+ </div>
125
+ </div>
114
126
  </div>
115
127
 
116
128
  <!-- Language Selector -->
117
129
  <div class="relative" ref="langMenuRef">
118
- <button @click="toggleLangMenu" class="px-2 py-1 rounded-md hover:bg-black/5 dark:hover:bg-white/10 cursor-pointer">
130
+ <button @click="toggleLangMenu" class="p-2 rounded-md hover:bg-black/5 dark:hover:bg-white/10 cursor-pointer">
119
131
  <HeroIcon name="language" size="22" color="text-current" />
120
132
  </button>
121
133
  <div
@@ -225,6 +237,10 @@
225
237
  const currentFontScale = computed(() => globalFontScale.value)
226
238
  const fontScaleAtMin = computed(() => globalFontScale.value <= FONT_SCALE_STEPS[0])
227
239
  const fontScaleAtMax = computed(() => globalFontScale.value >= FONT_SCALE_STEPS[FONT_SCALE_STEPS.length - 1])
240
+
241
+ const isA11yOpen = ref(false)
242
+ const a11yMenuRef = ref<HTMLElement | null>(null)
243
+ const toggleA11yMenu = () => (isA11yOpen.value = !isA11yOpen.value)
228
244
  /* ---------------------------------------------
229
245
  * layout integration
230
246
  ----------------------------------------------*/
@@ -307,7 +323,7 @@
307
323
  selectedRtl ? 'hidden md:flex md:mr-6 md:space-x-4 items-center' : 'hidden md:flex md:ml-6 md:space-x-4 items-center'
308
324
  )
309
325
 
310
- const actionsSpaceClass = computed(() => (selectedRtl ? 'space-x-2 space-x-reverse' : 'space-x-2'))
326
+ const actionsSpaceClass = computed(() => 'gap-2')
311
327
 
312
328
  const overflowPositionClass = computed(() => (selectedRtl ? 'left-0' : 'right-0'))
313
329
 
@@ -340,17 +356,13 @@
340
356
  }
341
357
 
342
358
  function onDocumentClick(e: MouseEvent) {
343
- if (!isLangOpen.value) return
344
- isLangOpen.value = false
345
- // const root = langMenuRef.value
346
- // const target = e.target as Node | null
347
- // if (!root || !target) {
348
- // isLangOpen.value = false
349
- // return
350
- // }
351
- // if (!root.contains(target)) {
352
- // isLangOpen.value = false
353
- // }
359
+ const target = e.target as Node | null
360
+ if (isLangOpen.value && langMenuRef.value && target && !langMenuRef.value.contains(target)) {
361
+ isLangOpen.value = false
362
+ }
363
+ if (isA11yOpen.value && a11yMenuRef.value && target && !a11yMenuRef.value.contains(target)) {
364
+ isA11yOpen.value = false
365
+ }
354
366
  }
355
367
 
356
368
  function getLangLabel(lang: string) {
@@ -206,7 +206,7 @@
206
206
  cellText,
207
207
  textAlign[header?.align ?? 'defaults'],
208
208
  ]"
209
- >
209
+ >
210
210
  <template v-if="getCustomColumnData(header, item)?.type === 'CopyTextBox'">
211
211
  <div class="flex flex-wrap items-center gap-1">
212
212
  <template
@@ -16,7 +16,7 @@
16
16
  type="text"
17
17
  :placeholder="searchPlaceholder"
18
18
  :class="[
19
- 'pl-10 pr-4 py-2 rounded-lg w-64 text-sm transition-colors focus:outline-none focus:ring-2 focus:ring-offset-0',
19
+ 'pl-10 pr-4 py-2 rounded-lg w-64 text-base transition-colors focus:outline-none focus:ring-2 focus:ring-offset-0',
20
20
  inputBorder
21
21
  ]"
22
22
  @input="debounceSearch"
@@ -44,7 +44,7 @@
44
44
  </div>
45
45
 
46
46
  <!-- Desktop Table View -->
47
- <table :dir="dir" class="w-full caption-bottom text-sm hidden md:table" style="table-layout: fixed;">
47
+ <table :dir="dir" class="w-full caption-bottom text-base hidden md:table" style="table-layout: fixed;">
48
48
  <!-- Colgroup for consistent column widths -->
49
49
  <colgroup>
50
50
  <col v-if="selectable" style="width: 48px;" />
@@ -146,7 +146,7 @@
146
146
  <svg class="w-12 h-12 text-gray-300 mb-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
147
147
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
148
148
  </svg>
149
- <span class="text-sm text-gray-500">{{ noDataText }}</span>
149
+ <span class="text-base text-gray-500">{{ noDataText }}</span>
150
150
  </div>
151
151
  </td>
152
152
  </tr>
@@ -196,7 +196,7 @@
196
196
  <!-- html -->
197
197
  <div
198
198
  v-if="header.displayType == 'html'" :class="[
199
- 'text-sm truncate',
199
+ 'text-base truncate',
200
200
  cellText,
201
201
  textAlign[header?.align ?? 'defaults'],
202
202
  ]" v-html="getCustomColumnData(header, item)"
@@ -205,22 +205,22 @@
205
205
  <!-- Custom column -->
206
206
  <div
207
207
  v-else-if="header.displayType == 'custom'" :class="[
208
- 'text-sm',
208
+ 'text-base truncate',
209
209
  cellText,
210
210
  textAlign[header?.align ?? 'defaults'],
211
211
  ]"
212
212
  >
213
213
  <template v-if="getCustomColumnData(header, item)?.type === 'CopyTextBox'">
214
- <div class="flex flex-wrap items-center gap-1">fff
214
+ <div class="flex flex-wrap items-center gap-1">
215
215
  <template
216
216
  v-for="(chip, idx) in getCustomColumnData(header, item).CopyTextBox"
217
217
  :key="idx"
218
- >dda
218
+ >
219
219
  <CopyTextBox
220
220
  :text="chip.text"
221
221
  class="mr-1 "
222
222
  />
223
- b
223
+
224
224
  </template>
225
225
  </div>
226
226
  </template>
@@ -232,7 +232,7 @@
232
232
  v-else-if="header.displayType == 'copyButton'"
233
233
  :class="['align-middle leading-0', getColumnFont(lang)]"
234
234
  >
235
-
235
+
236
236
  <CopyTextBox
237
237
  :text="getNestedValue(item, header.value)"
238
238
  class="mr-1 "
@@ -276,7 +276,7 @@
276
276
  v-bind="header.select"
277
277
  @update:model-value="(value) => handleCellUpdate(item, header.value, value, index)"
278
278
  />
279
- <div v-else :class="['text-sm', cellText]">
279
+ <div v-else :class="['text-base', cellText]">
280
280
  {{ formatCellValue(getNestedValue(item, header.value), header) }}
281
281
  </div>
282
282
  </div>
@@ -290,10 +290,10 @@
290
290
  v-if="editMode && header.inlineEditable"
291
291
  :value="getNestedValue(item, header.value)"
292
292
  type="text"
293
- class="w-full px-2 py-1 text-sm border rounded focus:outline-none focus:ring-2 focus:ring-primary"
293
+ class="w-full px-2 py-1 text-base border rounded focus:outline-none focus:ring-2 focus:ring-primary"
294
294
  @input="(e) => handleCellUpdate(item, header.value, e.target.value, index)"
295
295
  >
296
- <div v-else :class="['text-sm', cellText]">
296
+ <div v-else :class="['text-base', cellText]">
297
297
  {{ formatCellValue(getNestedValue(item, header.value), header) }}
298
298
  </div>
299
299
  </div>
@@ -308,11 +308,54 @@
308
308
  @view-file="emit('viewpdf', $event)"
309
309
  />
310
310
  </div>
311
+ <!-- Nested List Display -->
312
+ <div
313
+ v-else-if="header.displayType == 'nestedList'"
314
+ :class="['align-middle leading-normal', getColumnFont(lang)]"
315
+ >
316
+ <div
317
+ v-for="(nestedItem, nIdx) in (getNestedValue(item, header.value) || [])"
318
+ :key="nIdx"
319
+ :class="[
320
+ 'py-1.5',
321
+ nIdx > 0 ? 'border-t border-input-border' : ''
322
+ ]"
323
+ >
324
+ <div
325
+ v-for="col in header.nestedColumns"
326
+ :key="col.key"
327
+ class="flex items-center gap-2 py-0.5"
328
+ >
329
+ <span :class="['text-xs font-medium shrink-0 w-20', headerText]">
330
+ {{ col.label?.[lang] || col.label?.en || col.key }}
331
+ </span>
332
+ <div class="flex-1 min-w-0">
333
+ <!-- Chip -->
334
+ <Chip
335
+ v-if="col.displayType === 'chip' && col.chip?.[String(nestedItem[col.key])]"
336
+ v-bind="col.chip[String(nestedItem[col.key])]"
337
+ size="small"
338
+ />
339
+ <!-- HTML -->
340
+ <div
341
+ v-else-if="col.displayType === 'html'"
342
+ :class="['text-sm', cellText]"
343
+ v-html="nestedItem[col.key]"
344
+ />
345
+ <!-- Text (default) -->
346
+ <span v-else :class="['text-sm', cellText]">
347
+ {{ nestedItem[col.key] ?? '-' }}
348
+ </span>
349
+ </div>
350
+ </div>
351
+ </div>
352
+ <span v-if="!getNestedValue(item, header.value)?.length" class="text-xs text-gray-400">-</span>
353
+ </div>
311
354
 
312
355
  <!-- Default Text Display -->
313
356
  <bdi
314
357
  v-else :class="[
315
- 'text-sm',
358
+ 'text-base',
316
359
  cellText,
317
360
  textAlign[header.align ?? 'defaults'],
318
361
  header.displayType == 'englishText' || header.displayType == 'date' ? 'eng-font' : getColumnFont(lang),
@@ -351,7 +394,7 @@
351
394
  <svg class="w-12 h-12 text-gray-300 mb-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
352
395
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
353
396
  </svg>
354
- <span class="text-sm text-gray-500">{{ noDataText }}</span>
397
+ <span class="text-base text-gray-500">{{ noDataText }}</span>
355
398
  </div>
356
399
  </div>
357
400
 
@@ -398,8 +441,8 @@
398
441
  :header="header"
399
442
  :index="index"
400
443
  >
401
- <div v-if="header.displayType == 'html'" :class="['text-sm', cellText]" v-html="getCustomColumnData(header, item)" />
402
- <div v-else-if="header.displayType == 'custom'" :class="['text-sm', cellText]">
444
+ <div v-if="header.displayType == 'html'" :class="['text-base', cellText]" v-html="getCustomColumnData(header, item)" />
445
+ <div v-else-if="header.displayType == 'custom'" :class="['text-base', cellText]">
403
446
  <template v-if="getCustomColumnData(header, item)?.type === 'CopyTextBox'">
404
447
  <div class="flex flex-wrap items-center gap-1 justify-end">
405
448
  <CopyTextBox v-for="(chip, idx) in getCustomColumnData(header, item).CopyTextBox" :key="idx" v-bind="chip" />
@@ -420,7 +463,26 @@
420
463
  <div v-else-if="header.displayType == 'docButton'" :class="['align-middle', getColumnFont(header.lang)]">
421
464
  <FileDisplay :item="getNestedValue(item, header.value)" v-bind="header.docButton" @view-file="emit('viewpdf', $event)" />
422
465
  </div>
423
- <bdi v-else :class="['text-sm', cellText, header.displayType == 'englishText' || header.displayType == 'date' ? 'eng-font' : getColumnFont(lang)]">
466
+ <div v-else-if="header.displayType === 'nestedList'" :class="['align-middle', getColumnFont(lang)]">
467
+ <div
468
+ v-for="(nestedItem, nIdx) in (getNestedValue(item, header.value) || [])"
469
+ :key="nIdx"
470
+ :class="['py-1.5', nIdx > 0 ? 'border-t border-input-border' : '']"
471
+ >
472
+ <div v-for="col in header.nestedColumns" :key="col.key" class="flex items-center gap-2 py-0.5">
473
+ <span :class="['text-xs font-medium shrink-0 w-20', headerText]">
474
+ {{ col.label?.[lang] || col.label?.en || col.key }}
475
+ </span>
476
+ <div class="flex-1 min-w-0">
477
+ <Chip v-if="col.displayType === 'chip' && col.chip?.[String(nestedItem[col.key])]" v-bind="col.chip[String(nestedItem[col.key])]" size="small" />
478
+ <div v-else-if="col.displayType === 'html'" :class="['text-sm', cellText]" v-html="nestedItem[col.key]" />
479
+ <span v-else :class="['text-sm', cellText]">{{ nestedItem[col.key] ?? '-' }}</span>
480
+ </div>
481
+ </div>
482
+ </div>
483
+ <span v-if="!getNestedValue(item, header.value)?.length" class="text-xs text-gray-400">-</span>
484
+ </div>
485
+ <bdi v-else :class="['text-base', cellText, header.displayType == 'englishText' || header.displayType == 'date' ? 'eng-font' : getColumnFont(lang)]">
424
486
  {{ formatCellValue(getNestedValue(item, header.value), header) }}
425
487
  </bdi>
426
488
  </slot>
@@ -482,7 +544,7 @@
482
544
 
483
545
  title="Confirm Update"
484
546
  >
485
- <p class="text-sm text-gray-600 mb-6">
547
+ <p class="text-base text-gray-600 mb-6">
486
548
  Are you sure you want to update <strong>{{ pendingUpdate.header }}</strong>
487
549
  from <strong>{{ pendingUpdate.oldValue }}</strong> to <strong>{{ pendingUpdate.newValue }}</strong>?
488
550
  </p>
@@ -16,7 +16,7 @@
16
16
  :height="sizePx"
17
17
  viewBox="0 0 24 24"
18
18
  fill="none"
19
- stroke="currentColor"
19
+ :stroke="color"
20
20
  stroke-width="1.5"
21
21
  aria-hidden="true"
22
22
  >
@@ -2,7 +2,7 @@
2
2
  <main
3
3
  :class="['flex-1 w-full transition-padding duration-200', contentClass]"
4
4
  ref="el"
5
- :style="style"
5
+ :style="[style, contentFontStyle]"
6
6
  >
7
7
  <slot />
8
8
  </main>
@@ -14,10 +14,12 @@ import { ref, computed, inject, watch, onMounted } from "vue";
14
14
  const layout = inject<any>("layout", null);
15
15
  const el = ref<HTMLElement | null>(null);
16
16
 
17
+ const fontScaleMode = inject('fontScaleMode', ref('app'));
18
+ const globalFontScale = inject('globalFontScale', ref(100));
19
+
17
20
  const contentClass = computed(() => "");
18
21
 
19
22
  const style = computed(() => {
20
- // console.log("Layout in Main.vue horizontal:", layout?.horizontalOffset?.value);
21
23
  const top = layout?.topOffset?.value || 0;
22
24
  const bottom = layout?.bottomOffset?.value || 0;
23
25
  const { left, right } = layout?.horizontalOffset?.value || {
@@ -33,5 +35,25 @@ const style = computed(() => {
33
35
  };
34
36
  });
35
37
 
38
+ const contentFontStyle = computed(() => {
39
+ if (fontScaleMode.value !== 'body' || globalFontScale.value === 100) return {};
40
+ return {
41
+ '--content-font-scale': globalFontScale.value / 100,
42
+ fontSize: `${globalFontScale.value}%`,
43
+ };
44
+ });
45
+
36
46
  onMounted(() => {});
37
47
  </script>
48
+
49
+ <style>
50
+ /* Scale Tailwind text classes inside main when --content-font-scale is set.
51
+ Uses calc(original-rem * scale) so text scales without affecting layout (padding, width, etc.).
52
+ Specificity of `main .text-*` beats Tailwind's flat `.text-*`. */
53
+ main .text-xs { font-size: calc(0.75rem * var(--content-font-scale, 1)); }
54
+ main .text-sm { font-size: calc(0.875rem * var(--content-font-scale, 1)); }
55
+ main .text-base { font-size: calc(1rem * var(--content-font-scale, 1)); }
56
+ main .text-lg { font-size: calc(1.125rem * var(--content-font-scale, 1)); }
57
+ main .text-xl { font-size: calc(1.25rem * var(--content-font-scale, 1)); }
58
+ main .text-2xl { font-size: calc(1.5rem * var(--content-font-scale, 1)); }
59
+ </style>
@@ -193,7 +193,7 @@ function isActive(item: any) {
193
193
  backgroundColor: 'var(--vts-color-surface)',
194
194
  color: 'var(--vts-color-text)',
195
195
  borderRight: '1px solid var(--vts-color-border)',
196
- boxShadow: 'var(--vts-elevation-2)'
196
+ boxShadow: 'var(--vts-elevation-2)',
197
197
  }))
198
198
 
199
199
  const scrimThemeStyles = computed(() => ({
@@ -22,7 +22,7 @@
22
22
  </bdi>
23
23
 
24
24
  <div :class="['flex items-center gap-2 text-base font-medium', textColor]">
25
- <bdi :class="language == 'dv' ? 'text-right faruma' : 'text-left'">{{ startItem }}-{{ endItem }} {{ t('pagination.of') }} {{ itemsLength }}</bdi>
25
+ <bdi :class="language == 'dv' ? 'text-right faruma' : 'text-left'">{{ startItem }}-{{ endItem }} {{ itemsPerPage <= 1 ? t('pagination.of') : '' }} {{ itemsPerPage <= 1 ? itemsLength : '' }}</bdi>
26
26
  </div>
27
27
 
28
28
  <!-- Pagination controls -->
@@ -20,7 +20,7 @@
20
20
  {{ selectedlabels ? selectedlabels ?? selectedlabels.label : label }}
21
21
  </div>
22
22
  <!-- main -->
23
- <div class="flex items-center w-full gap-2 overflow-hidden min-w-0">
23
+ <div class="flex items-center w-full gap-2 overflow-hidden min-w-0 text-base">
24
24
  <div v-if="$slots.prepend || prepend" class="shrink-0">
25
25
  <slot name="prepend">
26
26
  <HeroIcon :size="iconSizes[size]" :name="prepend" :type="iconType == 'outline' ? 'outline' : 'solid'" />
@@ -434,11 +434,17 @@ function onInput(val) {
434
434
  // m on mount
435
435
  onMounted(() => {
436
436
  // Capture the initial width of the container to prevent it from growing
437
- nextTick(() => {
438
- if (inputContainerRef.value) {
439
- containerMaxWidth.value = inputContainerRef.value.offsetWidth + 'px'
440
- }
441
- })
437
+ // Use ResizeObserver to wait until the element actually has a width (avoids 0px on initial load)
438
+ if (inputContainerRef.value) {
439
+ const ro = new ResizeObserver((entries) => {
440
+ const width = entries[0]?.contentRect?.width
441
+ if (width > 0) {
442
+ containerMaxWidth.value = width + 'px'
443
+ ro.disconnect()
444
+ }
445
+ })
446
+ ro.observe(inputContainerRef.value)
447
+ }
442
448
  if (formContext) {
443
449
  formContext.register(uid, {
444
450
  rules: props.rules,
@@ -34,7 +34,7 @@
34
34
  <template #control="{ attrs, events }">
35
35
  <div
36
36
  :class="[
37
- 'flex-none items-center h-full gap-1 min-w-0 w-full overflow-hidden',
37
+ 'flex items-center h-full gap-1 min-w-0 w-full overflow-hidden',
38
38
  shouldAutoHeight ? 'flex-wrap py-1 -my-1' : '',
39
39
  ]"
40
40
  >
@@ -128,7 +128,7 @@
128
128
  name="chevron-down"
129
129
  type="outline"
130
130
  size="16"
131
- :class="['transition-transform duration-200', isOpen ? 'rotate-180' : '', 'text-input-border']"
131
+ :class="['transition-transform duration-200', isOpen ? 'rotate-180' : '',]"
132
132
  />
133
133
  <svg v-else-if="loading" class="animate-spin h-4 w-4 text-input-border" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
134
134
  <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
package/src/index.js CHANGED
@@ -17,8 +17,8 @@ import { drawerOpen } from './pgo-components/lib/drawerState.ts'
17
17
  import {globalRtl} from './pgo-components/lib/core/rtl/rtl.ts'
18
18
  import { setRtl } from './pgo-components/lib/core/rtl/setRtl.ts'
19
19
 
20
- import { globalFontScale } from './pgo-components/lib/core/fontSize/fontSize.ts'
21
- import { setFontScale, increaseFontScale, decreaseFontScale, resetFontScale } from './pgo-components/lib/core/fontSize/setFontScale.ts'
20
+ import { globalFontScale, fontScaleMode } from './pgo-components/lib/core/fontSize/fontSize.ts'
21
+ import { setFontScale, setFontScaleMode, increaseFontScale, decreaseFontScale, resetFontScale } from './pgo-components/lib/core/fontSize/setFontScale.ts'
22
22
 
23
23
  //components
24
24
  import {Button, Card, HeroIcon} from './components/pgo/index.ts' // for Global registration
@@ -31,7 +31,8 @@ export { globalRtl }
31
31
  export { setRtl }
32
32
  export { drawerOpen }
33
33
  export { globalFontScale }
34
- export { setFontScale, increaseFontScale, decreaseFontScale, resetFontScale }
34
+ export { setFontScale, setFontScaleMode, increaseFontScale, decreaseFontScale, resetFontScale }
35
+ export { fontScaleMode }
35
36
  // export { useSnackBar }
36
37
  export { _useTheme as useTheme }
37
38
  export { createThemePlugin } from './pgo-components/plugins/theme-plugin.js'
@@ -52,7 +53,9 @@ if (typeof window !== 'undefined') {
52
53
  window.__VTS_THEMES__ = Object.keys(themes)
53
54
  }
54
55
 
55
- // set font scale default
56
+ // set font scale mode from env, then restore saved scale
57
+ const scaleMode = import.meta.env.VITE_FONT_SCALE_MODE === 'body' ? 'body' : 'app'
58
+ setFontScaleMode(scaleMode)
56
59
  const savedFontScale = localStorage.getItem('fontScaleSetting')
57
60
  if (savedFontScale !== null) {
58
61
  setFontScale(parseInt(savedFontScale))
@@ -82,6 +85,7 @@ export default {
82
85
  app.provide('setRtl', setRtl)
83
86
  app.provide('drawerOpen', drawerOpen)
84
87
  app.provide('globalFontScale', globalFontScale)
88
+ app.provide('fontScaleMode', fontScaleMode)
85
89
  app.provide('increaseFontScale', increaseFontScale)
86
90
  app.provide('decreaseFontScale', decreaseFontScale)
87
91
  app.provide('resetFontScale', resetFontScale)
@@ -1,3 +1,4 @@
1
1
  import { ref } from "vue"
2
2
 
3
3
  export const globalFontScale = ref(100)
4
+ export const fontScaleMode = ref<'app' | 'body'>('app')
@@ -1,13 +1,23 @@
1
- import { globalFontScale } from './fontSize.ts'
1
+ import { globalFontScale, fontScaleMode } from './fontSize.ts'
2
2
 
3
3
  export const FONT_SCALE_STEPS = [85, 100, 115, 130, 145]
4
4
  const STORAGE_KEY = 'fontScaleSetting'
5
5
 
6
+ export function setFontScaleMode(mode: 'app' | 'body') {
7
+ fontScaleMode.value = mode
8
+ }
9
+
6
10
  export function setFontScale(percentage: number) {
7
11
  globalFontScale.value = percentage
8
12
  localStorage.setItem(STORAGE_KEY, String(percentage))
9
13
  if (typeof document !== 'undefined') {
10
- document.documentElement.style.fontSize = `${percentage}%`
14
+ if (fontScaleMode.value === 'app') {
15
+ document.documentElement.style.fontSize = `${percentage}%`
16
+ } else {
17
+ // In body mode, don't touch root font-size.
18
+ // Main.vue uses a CSS custom property to scale text only.
19
+ document.documentElement.style.fontSize = ''
20
+ }
11
21
  }
12
22
  }
13
23
 
@@ -1,4 +0,0 @@
1
- import { _ as f } from "./index-DXUeDVX5.js";
2
- export {
3
- f as default
4
- };