@osimart/create-storefront 1.0.25 → 1.0.26

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.
@@ -272,6 +272,7 @@
272
272
  <PhoneNumInput
273
273
  v-model="formData.mobile_number"
274
274
  variant="bare"
275
+ :themed-popup="true"
275
276
  :error="phoneHasError"
276
277
  @update="onPhoneUpdate"
277
278
  />
@@ -375,6 +376,7 @@
375
376
  @update:model-value="selectCountry($event); clearFieldError('country')"
376
377
  placeholder="Country"
377
378
  searchable
379
+ themed
378
380
  local-search
379
381
  full-width
380
382
  field="country"
@@ -408,6 +410,7 @@
408
410
  @update:model-value="selectZone($event); clearFieldError('zone')"
409
411
  placeholder="Zone"
410
412
  searchable
413
+ themed
411
414
  local-search
412
415
  full-width
413
416
  field="zone"
@@ -97,16 +97,20 @@
97
97
  <div
98
98
  v-if="open && !disabled"
99
99
  ref="menuRef"
100
- :style="[floatingStyles, menuWidthStyle, { zIndex: dropdownZIndex }]"
101
- class="absolute font-poppins bg-white border border-gray-300 rounded-md shadow-lg max-h-60 overflow-auto dropdown-select-popup"
102
- :class="dropdownWidth ? '' : 'w-max max-w-xs'"
100
+ :style="[floatingStyles, menuWidthStyle, themeVars, { zIndex: dropdownZIndex }]"
101
+ class="absolute font-poppins border rounded-md shadow-lg max-h-60 overflow-auto dropdown-select-popup"
102
+ :class="[
103
+ dropdownWidth ? '' : 'w-max max-w-xs',
104
+ themed ? 'dropdown-select-popup--themed' : 'bg-white border-gray-300',
105
+ ]"
103
106
  @scroll.passive="onScroll"
104
107
  >
105
108
  <!-- Search -->
106
109
  <div v-if="searchable" class="p-2">
107
110
  <input
108
111
  v-model="searchQuery"
109
- class="bg-input w-full border px-2 py-1 rounded text-sm focus:outline-none"
112
+ class="w-full border px-2 py-1 rounded text-sm focus:outline-none"
113
+ :class="themed ? 'dd-search' : 'bg-input'"
110
114
  placeholder="Search..."
111
115
  />
112
116
  </div>
@@ -116,7 +120,8 @@
116
120
  v-for="opt in filteredOptions"
117
121
  :key="opt.value"
118
122
  :style="{ color: opt.color }"
119
- class="px-4 py-2 flex justify-between items-center hover:bg-gray-100 cursor-pointer"
123
+ class="px-4 py-2 flex justify-between items-center cursor-pointer"
124
+ :class="themed ? 'dd-option' : 'hover:bg-gray-100'"
120
125
  @click="toggleOption(opt.value)"
121
126
  >
122
127
  <div class="flex items-center gap-2 min-w-0">
@@ -141,7 +146,7 @@
141
146
  </li>
142
147
  </ul>
143
148
 
144
- <div v-else-if="!loading" class="px-4 py-2 text-fifthosiblue text-center text-sm">
149
+ <div v-else-if="!loading" class="px-4 py-2 text-fifthosiblue text-center text-sm" :class="{ 'dd-empty': themed }">
145
150
  No results
146
151
  </div>
147
152
 
@@ -193,6 +198,11 @@ const props = defineProps({
193
198
  // Explicit width for the dropdown menu (any valid CSS width, e.g. '320px',
194
199
  // '24rem', '100%'). Overrides the default w-max/max-w-xs/minWidth-match behavior.
195
200
  dropdownWidth: { type: String, default: null },
201
+ // Opt-in: the popup takes its colours from the storefront theme variables
202
+ // (the same ones the form fields use) instead of the hardcoded white/gray.
203
+ // The menu is teleported to <body>, so the variables are copied from the
204
+ // trigger's element when it opens. Off = every existing usage is unchanged.
205
+ themed: { type: Boolean, default: false },
196
206
  });
197
207
  const parentModalZIndex = inject("modalZIndex", null);
198
208
  const dropdownZIndex = computed(() =>
@@ -211,6 +221,38 @@ const rootRef = ref(null);
211
221
  const triggerBtnRef = ref(null);
212
222
  const triggerWidth = ref(0);
213
223
 
224
+ // CSS variables the themed popup needs. The teleported menu sits outside the
225
+ // element that defines them, so they're read from the trigger when it opens.
226
+ // Names match osi-controls.css: the Inputs theme group (--osi-input-*) and the
227
+ // colour scheme (--osi-bg / --osi-text / --osi-border).
228
+ const THEME_VARS = [
229
+ "--osi-bg",
230
+ "--osi-text",
231
+ "--osi-border",
232
+ "--osi-input-bg",
233
+ "--osi-input-fg",
234
+ "--osi-input-border-color",
235
+ // The checkout's card colours (set inline on .osi-ck, so only present there).
236
+ "--ck-card-bg",
237
+ "--ck-card-text",
238
+ "--ck-card-border",
239
+ ];
240
+ const themeVars = ref({});
241
+
242
+ function readThemeVars() {
243
+ if (!props.themed || !rootRef.value) {
244
+ themeVars.value = {};
245
+ return;
246
+ }
247
+ const cs = getComputedStyle(rootRef.value);
248
+ const vars = {};
249
+ for (const name of THEME_VARS) {
250
+ const value = cs.getPropertyValue(name).trim();
251
+ if (value) vars[name] = value;
252
+ }
253
+ themeVars.value = vars;
254
+ }
255
+
214
256
  const menuWidthStyle = computed(() => {
215
257
  if (props.dropdownWidth) return { width: props.dropdownWidth };
216
258
  if (!props.autoWidth) return { minWidth: triggerWidth.value + 'px' };
@@ -410,6 +452,7 @@ watch(open, (isOpen) => {
410
452
  if (isOpen) {
411
453
  eventBus.emit("dropdown:opened", instanceId);
412
454
  triggerWidth.value = rootRef.value ? rootRef.value.offsetWidth : 0;
455
+ readThemeVars();
413
456
  document.addEventListener("mousedown", handleDocumentClick, true);
414
457
  emit("open");
415
458
  } else {
@@ -429,4 +472,30 @@ onBeforeUnmount(() => {
429
472
  onUnmounted(() => {
430
473
  eventBus.off("dropdown:opened", onGlobalDropdownOpened);
431
474
  });
432
- </script>
475
+ </script>
476
+
477
+ <style scoped>
478
+ /* Only applied when the `themed` prop is set. Every colour falls back to the
479
+ old hardcoded one, so a themed popup outside the storefront still looks
480
+ the same as before. */
481
+ .dropdown-select-popup--themed {
482
+ background: var(--osi-input-bg, var(--ck-card-bg, var(--osi-bg, #fff)));
483
+ color: var(--osi-input-fg, var(--ck-card-text, var(--osi-text, inherit)));
484
+ border-color: var(--osi-input-border-color, var(--ck-card-border, var(--osi-border, #d1d5db)));
485
+ }
486
+ .dropdown-select-popup--themed .dd-option:hover {
487
+ background: color-mix(in srgb, currentColor 8%, transparent);
488
+ }
489
+ .dropdown-select-popup--themed .dd-search {
490
+ background: transparent;
491
+ color: inherit;
492
+ border-color: color-mix(in srgb, currentColor 20%, transparent);
493
+ }
494
+ .dropdown-select-popup--themed .dd-search::placeholder {
495
+ color: color-mix(in srgb, currentColor 50%, transparent);
496
+ }
497
+ .dropdown-select-popup--themed .dd-empty {
498
+ color: inherit;
499
+ opacity: 0.6;
500
+ }
501
+ </style>
@@ -14,6 +14,7 @@
14
14
  :searchable="true"
15
15
  :local-search="true"
16
16
  smallText
17
+ themed
17
18
  @search="onSearch"
18
19
  @update:modelValue="onCountryChange"
19
20
  @open="isFocused = true"
@@ -64,7 +65,8 @@
64
65
  v-else
65
66
  class="w-full"
66
67
  :class="[
67
- effectiveVariant === 'underline' ? 'font-thoren relative' : 'font-poppins'
68
+ effectiveVariant === 'underline' ? 'font-thoren relative' : 'font-poppins',
69
+ { 'phone-input-themed': themedPopup && effectiveVariant === 'bare' }
68
70
  ]"
69
71
  >
70
72
  <label
@@ -100,6 +102,7 @@
100
102
  @update:modelValue="onCountryChange"
101
103
  @open="isFocused = true"
102
104
  @close="isFocused = false"
105
+ :themed="themedPopup"
103
106
  :fullWidth="false"
104
107
  class="shrink min-w-[90px]"
105
108
  :class="ispopup ? 'lg:min-w-[70px]':'lg:min-w-[140px]'"
@@ -196,6 +199,9 @@ const props = defineProps({
196
199
  inputClass: { type: [String, Array, Object], default: 'osi-input' },
197
200
  inputId: { type: String, default: '' },
198
201
  disabled: { type: Boolean, default: false },
202
+ // Non-theme variants only: opt the country popup into the theme colours.
203
+ // (The `theme` variant is always themed.)
204
+ themedPopup: { type: Boolean, default: false },
199
205
  })
200
206
 
201
207
  const emit = defineEmits(['update:modelValue', 'update', 'clear-error'])
@@ -431,4 +437,20 @@ const getFlagUrl = (code) => {
431
437
  outline: none !important;
432
438
  box-shadow: none !important;
433
439
  }
434
- </style>
440
+
441
+ /* Keep the compact bare layout while using the shared Inputs color tokens. */
442
+ .phone-input-themed .dropdown-trigger-btn,
443
+ .phone-input-themed .text-input {
444
+ color: var(--osi-input-fg, inherit);
445
+ }
446
+ .phone-input-themed .text-input {
447
+ background-color: var(--osi-input-bg, transparent);
448
+ }
449
+ .phone-input-themed .text-input::placeholder {
450
+ color: var(--osi-input-placeholder, currentColor);
451
+ opacity: 1;
452
+ }
453
+ .phone-input-themed .border-r {
454
+ border-color: var(--osi-input-border-color, #e5e7eb);
455
+ }
456
+ </style>
@@ -146,6 +146,8 @@ export default function useLogic() {
146
146
  if (s.HEADER_ICON_BORDER) style["--osi-header-icon-border"] = s.HEADER_ICON_BORDER;
147
147
  if (s.HEADER_CART_BADGE_BG) style["--osi-header-badge-bg"] = s.HEADER_CART_BADGE_BG;
148
148
  if (s.HEADER_CART_BADGE_TEXT) style["--osi-header-badge-text"] = s.HEADER_CART_BADGE_TEXT;
149
+ if (s.HEADER_BORDER_COLOR) style["--osi-header-border"] = s.HEADER_BORDER_COLOR;
150
+ if (s.HEADER_BORDER_WIDTH) style["--osi-header-border-w"] = `${s.HEADER_BORDER_WIDTH}px`;
149
151
  style["--osi-header-pad-y"] = `${s.HEADER_PADDING_Y}px`;
150
152
  // Side padding lives on the header itself, not on the inner box — see the
151
153
  // note on .osi-header-inner below. 16 is COMMON_STYLE_SETTINGS' PADDING_X
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@osimart/create-storefront",
3
- "version": "1.0.25",
3
+ "version": "1.0.26",
4
4
  "description": "Osimart storefront platform — logic, platform pages and CLI; extended by every theme repo",
5
5
  "type": "module",
6
6
  "main": "./nuxt.config.ts",