@osimart/create-storefront 1.0.25 → 1.0.27

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
@@ -1,42 +1,99 @@
1
- # @osimart/create-storefront
1
+ # Osimart Storefront
2
2
 
3
- The Osimart storefront **platform**, published as a private Nuxt layer. It has no look of
4
- its own. Every theme repo extends it:
3
+ `@Osimart/create-storefront` is the shared storefront platform for Osimart themes. It provides the Nuxt foundation, store-facing pages, commerce behavior, reusable UI, theme integration, and the `Osimart-theme` developer CLI. A theme extends this package and supplies its own presentation: page layouts, section markup, component styling, assets, and theme configuration.
4
+
5
+ This package is intended to be consumed by an Osimart theme project. It is not a standalone store template. The theme project is where you build the customer-facing look; this package supplies the shared platform that powers it.
6
+
7
+ ## How the pieces fit together
8
+
9
+ | Part | Owns |
10
+ | --- | --- |
11
+ | `@Osimart/create-storefront` (this package) | Nuxt configuration, routes, shared commerce and account behavior, platform components, theme utilities, and the theme CLI |
12
+ | Osimart theme project | Layouts, section and component markup, CSS, images and fonts, section schemas, and theme JSON settings |
13
+ | Osimart store service | Store data and API operations used by the storefront and theme tools |
14
+
15
+ The platform exposes logic for theme files through `#logic`. A theme can use that logic while keeping control of its Vue template and styles. This lets shared behavior improve across themes without forcing every theme to use the same design.
16
+
17
+ ## Requirements
18
+
19
+ - Node.js and npm versions supported by your Nuxt project.
20
+ - An Osimart theme repository or a new theme project based on the Osimart theme structure.
21
+ - Access to the `@osimart/create-storefront` package registry if the package is private in your environment.
22
+ - An Osimart store API URL and a theme access token for commands that read or write a store's theme.
23
+
24
+ ## Add the platform to a theme project
25
+
26
+ Install the package in the theme project:
27
+
28
+ ```bash
29
+ npm install @osimart/create-storefront
30
+ ```
31
+
32
+ If registry authentication is required, configure npm using the credentials provided for your Osimart development environment. Do not commit access tokens to the repository.
33
+
34
+ Extend the platform from the theme's `nuxt.config.ts`:
5
35
 
6
36
  ```ts
7
- // osimart-theme-base/nuxt.config.ts, store-offsiders/nuxt.config.ts, …
8
- export default defineNuxtConfig({ extends: ["@osimart/create-storefront"] });
37
+ export default defineNuxtConfig({
38
+ extends: ["@osimart/create-storefront"],
39
+ });
40
+ ```
41
+
42
+ The layer configures the `#osi` alias for platform app code, the `#logic` alias for shared theme logic, global platform components, and the section registry module. The theme can add its own components and section files in the usual Nuxt locations.
43
+
44
+ Install the theme project's remaining dependencies and start it using its scripts. For example, the Osimart base theme uses:
45
+
46
+ ```bash
47
+ npm install
48
+ npm run dev
9
49
  ```
10
50
 
11
- | | Shopify | Osimart |
12
- |---|---|---|
13
- | Platform (hidden, updates everyone) | Shopify's servers | this package |
14
- | Theme (Dawn) | sections, snippets, layout, assets | `osimart-theme-base` repo |
15
- | Theme JSON | `templates/*.json`, `sections/*-group.json`, `config/settings_data.json` | `theme/` in the theme repo, `osimart-theme pull/push` |
16
- | A store's custom theme | copy of Dawn | a repo created from `osimart-theme-base` |
51
+ The base theme's `dev` script runs `Osimart-theme dev`, which starts Nuxt in a theme development session. Use `npm run dev:live` when you specifically need to run plain `nuxt dev` without the theme preview session.
17
52
 
18
- ## What's here
53
+ ## Configure the store connection
19
54
 
55
+ Set environment variables in the theme project's local `.env` file. The exact API host depends on your Osimart environment:
56
+
57
+ ```dotenv
58
+ NUXT_PUBLIC_STORE_API_BASE=https://your-store-api.example/
59
+ Osimart_THEME_TOKEN=your-theme-access-token
20
60
  ```
61
+
62
+ `NUXT_PUBLIC_STORE_API_BASE` is the API base used by the storefront. The theme CLI also uses it to reach the theme development API. `Osimart_THEME_TOKEN` authorizes theme CLI operations. Keep the token private and out of source control.
63
+
64
+ In production, the storefront API is same-origin by default; the Nuxt runtime config's `storeApiBase` defaults to an empty string. Configure the deployment and API routing for your Osimart environment accordingly. The public runtime setting can be overridden with `NUXT_PUBLIC_STORE_API_BASE` when needed.
65
+
66
+ ## Project structure
67
+
68
+ The main platform areas are:
69
+
70
+ ```text
21
71
  app/
22
- ├── logic/ the script of every theme file — the theme only imports it
23
- │ ├── sections/ HeroSection.js, MainProductSection.js, … (#logic/sections/…)
24
- │ ├── components/ ProductCard.js, SiteHeader.js, … (#logic/components/…)
25
- │ └── layouts/default.js
26
- ├── composables/ services/ utils/ stores/ plugins/
27
- ├── pages/ routes: index, [category]/[product], categories/[slug], search,
28
- │ pages/[handle] (each = "render this path's template");
29
- │ checkout, login, user-profile, order-detail… (platform pages)
30
- ├── components/ platform UI: SectionRenderer, builder/, checkout/,
31
- │ common/ (OsiField, PhoneNumInput, DropdownSelect, Banner…)
32
- ├── theme/ registry.js (section map), controls.js, categoryTree.js
33
- └── app.vue
34
- bin/osimart-theme.mjs CLI: themes / pull / push / publish
35
- nuxt/osi-sections.ts builds the section map from the theme's app/sections
36
- THEME_DEV_API.md the backend endpoints the CLI calls
72
+ ├── logic/
73
+ │ ├── sections/ Shared behavior used by theme section components
74
+ │ ├── components/ Shared behavior used by theme components
75
+ │ └── layouts/ Shared layout behavior
76
+ ├── pages/ Platform routes such as checkout, login, and account pages
77
+ ├── components/
78
+ │ ├── checkout/ Checkout UI
79
+ │ ├── common/ Shared controls and UI primitives
80
+ │ └── builder/ Theme builder and preview UI
81
+ ├── composables/ Reusable Vue/Nuxt behavior
82
+ ├── services/ API and domain service code
83
+ ├── stores/ Pinia stores
84
+ └── theme/ Theme registries and control helpers
85
+ bin/Osimart-theme.mjs Theme development and synchronization CLI
86
+ nuxt/ Nuxt modules for section registration and dev preview
87
+ THEME_DEV_API.md Theme CLI API contract
37
88
  ```
38
89
 
39
- A theme section looks like this — markup and CSS in the theme, logic from here:
90
+ The consuming theme typically contains its own `app/sections`, `app/components`, `app/layouts`, styles, public assets, and a `theme/` directory with its settings, section groups, and page templates.
91
+
92
+ ## Customize a theme
93
+
94
+ ### Change a section's markup or styling
95
+
96
+ Theme section files own their template and CSS. Import the matching platform logic when the section needs shared data or behavior:
40
97
 
41
98
  ```vue
42
99
  <script setup>
@@ -46,36 +103,111 @@ const props = defineProps({ section: Object, index: Number });
46
103
  const { asBanner } = useLogic({ props });
47
104
  </script>
48
105
 
49
- <template><MediaWithTextSection :section="asBanner" :index="index" /></template>
106
+ <template>
107
+ <MediaWithTextSection :section="asBanner" :index="index" />
108
+ </template>
109
+
110
+ <style scoped>
111
+ /* Theme-specific presentation */
112
+ </style>
113
+ ```
114
+
115
+ Keep the props and emitted events expected by the shared component logic. The logic's returned values are part of the theme integration API: adding a returned value is generally compatible, while renaming or removing one can break consuming themes.
116
+
117
+ ### Override a platform component
118
+
119
+ Create a theme component with the same component name and Nuxt will resolve the theme implementation for that theme. Use the shared component logic where appropriate, then own the template and style in the theme. This is useful when a theme needs a different design while preserving established cart, product, or navigation behavior.
120
+
121
+ ### Add a section type
122
+
123
+ Create a Vue section and its schema in the theme project. For example:
124
+
125
+ `app/sections/LookbookSection.vue`
126
+
127
+ ```vue
128
+ <script setup>
129
+ const props = defineProps({ section: Object, index: Number });
130
+ </script>
131
+
132
+ <template>
133
+ <section class="lookbook">
134
+ <h2>{{ section.settings?.HEADING }}</h2>
135
+ </section>
136
+ </template>
137
+ ```
138
+
139
+ `app/sections/LookbookSection.schema.json`
140
+
141
+ ```json
142
+ {
143
+ "name": "Lookbook",
144
+ "templates": ["INDEX", "PAGE"],
145
+ "settings": [
146
+ { "id": "HEADING", "type": "text", "label": "Heading" }
147
+ ],
148
+ "blocks": []
149
+ }
50
150
  ```
51
151
 
52
- `useLogic` returns everything the original `<script setup>` declared, so the template can use
53
- any of it. Changing the logic changes every theme after its next build; the theme's markup
54
- and CSS are untouched.
152
+ The section registry discovers theme section files. The schema describes the settings and blocks available to the Osimart theme editor. Push the theme to synchronize the schema with the store, then add the section to the relevant theme template or group.
153
+
154
+ ### Customize theme settings and page composition
155
+
156
+ Theme JSON is stored in the theme project's `theme/` directory:
157
+
158
+ ```text
159
+ theme/
160
+ ├── config/settings_data.json
161
+ ├── sections/header-group.json
162
+ ├── sections/footer-group.json
163
+ └── templates/
164
+ ├── index.json
165
+ ├── product.json
166
+ └── page.contact.json
167
+ ```
168
+
169
+ Use the theme CLI to pull the current store theme, edit its JSON locally, and push changes to a draft. This supports working in version control while keeping the dashboard theme editor as another way to manage the same theme data.
170
+
171
+ ## Theme development CLI
55
172
 
56
- ## Rules for code in this package
173
+ The package exposes the `Osimart-theme` executable. The Osimart base theme provides npm scripts for common commands:
57
174
 
58
- - Never import with `~/` — inside a layer it means the theme. Use `#osi/…` (this `app/`),
59
- `#logic/…`, or `#components` (which picks the theme's component when it has one).
60
- - `useLogic` return keys are the theme's API. Adding a key is a minor release; renaming or
61
- removing one breaks themes, so it's a major.
62
- - A logic file with a top-level `await` wraps it in `withAsyncContext` (already done for
63
- `AnnouncementBar.js`) so composables after it still have the component instance.
175
+ | Command | Purpose |
176
+ | --- | --- |
177
+ | `npm run dev` | Start a Nuxt theme development session against a store draft; saves in `theme/` are synchronized during the session. |
178
+ | `npm run theme:list` | List themes available to the configured store. |
179
+ | `npm run theme:pull` | Pull the live theme into local `theme/` files. |
180
+ | `npm run theme:pull -- --theme <id>` | Pull a specific theme by ID. |
181
+ | `npm run theme:push` | Push local theme files to a draft theme. |
182
+ | `npm run theme:push -- --theme live` | Push directly to the live theme. Use with care. |
183
+ | `npx Osimart-theme publish <id>` | Make the specified theme live. |
64
184
 
65
- ## Releasing
185
+ The CLI also supports `--dry-run`, `--force`, and `--prune` on push, and `--delete` on pull. Run `npx Osimart-theme` to print its usage. A normal push checks whether the remote theme changed since the last pull; pull and reconcile those edits before pushing, or use `--force` when intentionally replacing the remote version.
66
186
 
67
- 1. Bump `version` (semver): patch/minor for fixes and additions, **major** if a `useLogic`
68
- key, a component's props or a route changes.
69
- 2. `git tag v1.4.0 && git push --tags` → `release.yml` publishes to GitHub Packages and sends
70
- `storefront-release` to every repo in `STORE_REPOS`; each one updates and redeploys.
187
+ ## Customizing platform behavior
71
188
 
72
- Repo setup once: secret `STORES_DISPATCH_TOKEN` (fine-grained PAT, contents read/write on the
73
- theme repos), variable `STORE_REPOS` (`ositcom/osimart-theme-base ositcom/store-offsiders`).
74
- Package settings: *Manage Actions access* → every theme repo; *Manage access* → each outside
75
- developer (read).
189
+ If you are developing this package itself, shared behavior lives under `app/logic`, reusable platform UI under `app/components`, and shared Nuxt/Vue behavior under `app/composables`, `app/services`, and `app/stores`. Prefer changing shared logic here when the behavior should apply to all Osimart themes. Prefer changing a theme's Vue/CSS when the change is visual or unique to one storefront.
76
190
 
77
- ## Working on the platform and a theme together
191
+ Inside this Nuxt layer, avoid `~/` imports because `~` resolves to the consuming theme. Use:
192
+
193
+ - `#osi/...` for this package's app files, such as composables and services.
194
+ - `#logic/...` for shared section and component logic.
195
+ - `#components` when using components that a theme may override.
196
+
197
+ Treat component props, emitted events, routes, and the objects returned by `useLogic` as public integration points. Update theme consumers when changing those contracts.
198
+
199
+ ## Package development and releases
200
+
201
+ To work on a theme and a local copy of this package together, link the package into the theme project, then run the theme's development command. For example, from the theme project:
78
202
 
79
203
  ```bash
80
- cd osimart-theme-base && npm link ../create-storefront && npm run dev
204
+ npm link ../osimart-storefront
205
+ npm run dev
81
206
  ```
207
+
208
+ Package releases use semantic versioning. Compatible fixes and additions should preserve existing theme APIs; breaking changes to public component props, routes, or logic return values should be treated as major changes. Theme projects can update the dependency with their package manager and then rebuild/redeploy through their normal Osimart deployment process.
209
+
210
+ ## More information
211
+
212
+ - [Osimart theme development API](./THEME_DEV_API.md) — endpoints and payloads used by the theme CLI.
213
+ - The Osimart base theme README — theme project setup, theme file structure, deployment, and theme-specific customization examples.
@@ -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.27",
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",