pgo-ui 1.0.78 → 1.0.79

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.79",
4
4
  "description": "A Vue 3 component library with PGO design system",
5
5
  "private": false,
6
6
  "type": "module",
@@ -17,7 +17,7 @@
17
17
  densityClass,
18
18
  collapseClass
19
19
  ]"
20
- :style="[themeStyles, customStyle,]"
20
+ :style="[themeStyles, customStyle, fontPinStyle]"
21
21
  >
22
22
  <div
23
23
  :class="['w-full flex items-center justify-between', innerDirectionClass, dense ? 'h-12' : 'h-16']"
@@ -86,31 +86,43 @@
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="px-2 py-1 rounded-md hover:bg-black/5 dark:hover:bg-white/10 cursor-pointer">
92
+ <HeroIcon name="user-circle" size="22" color="text-current" />
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 -->
@@ -211,6 +223,8 @@
211
223
  })
212
224
 
213
225
  const globalRtl = inject('globalRtl', ref(false))
226
+ const fontScaleMode = inject('fontScaleMode', ref('app'))
227
+ const fontPinStyle = computed(() => fontScaleMode.value === 'body' ? { fontSize: '16px' } : {})
214
228
  const selectedRtl = computed(() => props.rtl !== undefined ? props.rtl : globalRtl.value)
215
229
 
216
230
  /* ---------------------------------------------
@@ -225,6 +239,10 @@
225
239
  const currentFontScale = computed(() => globalFontScale.value)
226
240
  const fontScaleAtMin = computed(() => globalFontScale.value <= FONT_SCALE_STEPS[0])
227
241
  const fontScaleAtMax = computed(() => globalFontScale.value >= FONT_SCALE_STEPS[FONT_SCALE_STEPS.length - 1])
242
+
243
+ const isA11yOpen = ref(false)
244
+ const a11yMenuRef = ref<HTMLElement | null>(null)
245
+ const toggleA11yMenu = () => (isA11yOpen.value = !isA11yOpen.value)
228
246
  /* ---------------------------------------------
229
247
  * layout integration
230
248
  ----------------------------------------------*/
@@ -340,17 +358,13 @@
340
358
  }
341
359
 
342
360
  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
- // }
361
+ const target = e.target as Node | null
362
+ if (isLangOpen.value && langMenuRef.value && target && !langMenuRef.value.contains(target)) {
363
+ isLangOpen.value = false
364
+ }
365
+ if (isA11yOpen.value && a11yMenuRef.value && target && !a11yMenuRef.value.contains(target)) {
366
+ isA11yOpen.value = false
367
+ }
354
368
  }
355
369
 
356
370
  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
  >
@@ -17,7 +17,6 @@ const el = ref<HTMLElement | null>(null);
17
17
  const contentClass = computed(() => "");
18
18
 
19
19
  const style = computed(() => {
20
- // console.log("Layout in Main.vue horizontal:", layout?.horizontalOffset?.value);
21
20
  const top = layout?.topOffset?.value || 0;
22
21
  const bottom = layout?.bottomOffset?.value || 0;
23
22
  const { left, right } = layout?.horizontalOffset?.value || {
@@ -189,11 +189,13 @@ function isActive(item: any) {
189
189
  return item.href === currentPath.value
190
190
  }
191
191
 
192
+ const fontScaleMode = inject('fontScaleMode', ref('app'))
192
193
  const themeStyles = computed(() => ({
193
194
  backgroundColor: 'var(--vts-color-surface)',
194
195
  color: 'var(--vts-color-text)',
195
196
  borderRight: '1px solid var(--vts-color-border)',
196
- boxShadow: 'var(--vts-elevation-2)'
197
+ boxShadow: 'var(--vts-elevation-2)',
198
+ ...(fontScaleMode.value === 'body' ? { fontSize: '16px' } : {}),
197
199
  }))
198
200
 
199
201
  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,12 +1,18 @@
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') {
14
+ // Always set root font-size so rem-based text scales.
15
+ // In "body" mode, AppBar/NavigationDrawer pin themselves at 16px.
10
16
  document.documentElement.style.fontSize = `${percentage}%`
11
17
  }
12
18
  }
@@ -1,4 +0,0 @@
1
- import { _ as f } from "./index-DXUeDVX5.js";
2
- export {
3
- f as default
4
- };