@zenky/storefront-vue 0.10.0 → 0.10.4
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/CHANGELOG.md +105 -0
- package/README.md +66 -6
- package/dist/cart/index.d.ts +31 -2
- package/dist/cart/index.js +6 -9
- package/dist/catalog/index.d.ts +1 -11
- package/dist/catalog/index.js +2 -2
- package/dist/chunk-2CI4RW7V.js +21 -0
- package/dist/chunk-2CI4RW7V.js.map +1 -0
- package/dist/{chunk-GW2QNTAD.js → chunk-4IFPVEO7.js} +3 -113
- package/dist/chunk-4IFPVEO7.js.map +1 -0
- package/dist/{chunk-EYRCAUUP.js → chunk-E3G7NGCH.js} +2 -2
- package/dist/chunk-E3G7NGCH.js.map +1 -0
- package/dist/{chunk-IGDDWGS4.js → chunk-IVG4FQE5.js} +21 -13
- package/dist/chunk-IVG4FQE5.js.map +1 -0
- package/dist/{chunk-PJ2LEKW6.js → chunk-MZ66ARDL.js} +18 -3
- package/dist/chunk-MZ66ARDL.js.map +1 -0
- package/dist/{chunk-2OD7CLKD.js → chunk-NG7RUIWW.js} +3 -13
- package/dist/chunk-NG7RUIWW.js.map +1 -0
- package/dist/{chunk-VL3T36VM.js → chunk-NIQFYJRP.js} +53 -9
- package/dist/chunk-NIQFYJRP.js.map +1 -0
- package/dist/{chunk-AL5W5JSD.js → chunk-OTSAR32A.js} +6 -3
- package/dist/chunk-OTSAR32A.js.map +1 -0
- package/dist/{chunk-BIGTKVC6.js → chunk-SS7B2NLF.js} +3 -3
- package/dist/{chunk-BIGTKVC6.js.map → chunk-SS7B2NLF.js.map} +1 -1
- package/dist/{chunk-PWHIDGKW.js → chunk-TB5TBJ4U.js} +53 -6
- package/dist/chunk-TB5TBJ4U.js.map +1 -0
- package/dist/{chunk-4MJKN7PL.js → chunk-YREGCQSB.js} +4 -6
- package/dist/chunk-YREGCQSB.js.map +1 -0
- package/dist/{chunk-OQLU7FSR.js → chunk-YS5DXYYV.js} +228 -51
- package/dist/chunk-YS5DXYYV.js.map +1 -0
- package/dist/index.d.ts +6 -8
- package/dist/index.js +14 -16
- package/dist/order/index.d.ts +2 -0
- package/dist/order/index.js +2 -5
- package/dist/order/index.js.map +1 -1
- package/dist/pagination/index.js.map +1 -1
- package/dist/ports/index.d.ts +12 -1
- package/dist/ports/index.js +1 -1
- package/dist/products/index.js +3 -4
- package/dist/promotions/index.js +3 -5
- package/dist/seo/index.d.ts +5 -11
- package/dist/seo/index.js +17 -27
- package/dist/seo/index.js.map +1 -1
- package/dist/snippets/index.d.ts +21 -15
- package/dist/snippets/index.js +1 -1
- package/dist/stores/index.d.ts +1 -1
- package/dist/stores/index.js +3 -5
- package/dist/theme/index.d.ts +1 -11
- package/dist/theme/index.js +1 -1
- package/dist/utils/index.d.ts +28 -5
- package/dist/utils/index.js +1 -1
- package/dist/website-settings/index.d.ts +1 -1
- package/docs/consumer-setup.md +279 -0
- package/docs/ports.md +148 -0
- package/docs/releasing.md +53 -0
- package/package.json +27 -8
- package/dist/chunk-2OD7CLKD.js.map +0 -1
- package/dist/chunk-4MJKN7PL.js.map +0 -1
- package/dist/chunk-AL5W5JSD.js.map +0 -1
- package/dist/chunk-BWUKMWHL.js +0 -45
- package/dist/chunk-BWUKMWHL.js.map +0 -1
- package/dist/chunk-DKWDKVXQ.js +0 -91
- package/dist/chunk-DKWDKVXQ.js.map +0 -1
- package/dist/chunk-EYRCAUUP.js.map +0 -1
- package/dist/chunk-GW2QNTAD.js.map +0 -1
- package/dist/chunk-IGDDWGS4.js.map +0 -1
- package/dist/chunk-OQLU7FSR.js.map +0 -1
- package/dist/chunk-PJ2LEKW6.js.map +0 -1
- package/dist/chunk-PWHIDGKW.js.map +0 -1
- package/dist/chunk-V3VVDQIR.js +0 -27
- package/dist/chunk-V3VVDQIR.js.map +0 -1
- package/dist/chunk-VL3T36VM.js.map +0 -1
- package/dist/layout/index.d.ts +0 -54
- package/dist/layout/index.js +0 -102
- package/dist/layout/index.js.map +0 -1
- package/dist/schedule-Dd3zwHEb.d.ts +0 -27
- package/dist/snippets-BC5bkSjm.d.ts +0 -23
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented in this file. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and releases follow
|
|
5
|
+
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
|
+
|
|
7
|
+
## 0.10.4 - 2026-07-29
|
|
8
|
+
|
|
9
|
+
> **Breaking.** This release changes the runtime port contract and removes public
|
|
10
|
+
> exports. The version stays in the `0.10.x` range because the package has no stable
|
|
11
|
+
> release yet and has a single, already-migrated consumer. Read the migration notes
|
|
12
|
+
> below before upgrading.
|
|
13
|
+
|
|
14
|
+
### Migration
|
|
15
|
+
|
|
16
|
+
1. **Provide the `messages` port.** `StorefrontRuntime` now requires a
|
|
17
|
+
`MessageFormatter`. `createStorefront()` and `provideStorefront()` throw on start
|
|
18
|
+
when any required port is missing, instead of failing later inside a `catch` block.
|
|
19
|
+
Tests and headless consumers can pass `KEY_MESSAGE_FORMATTER`, which returns the key
|
|
20
|
+
itself.
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
import { KEY_MESSAGE_FORMATTER } from '@zenky/storefront-vue/ports'
|
|
24
|
+
|
|
25
|
+
app.use(createStorefront({ ...runtime, messages: KEY_MESSAGE_FORMATTER }))
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
2. **Move removed symbols into your app.** Gone from their subpath *and* from the root
|
|
29
|
+
entry: `catalogRoutes` (`./catalog`), `THEME_PRESETS` / `DARK_THEME_PRESETS` /
|
|
30
|
+
`ThemePreset` (`./theme`), `buildSnippetHead` / `SnippetHead` (`./snippets`). Gone
|
|
31
|
+
from their subpath only: `withSeoMetaPriority` (`./seo`) and the entire `./layout`
|
|
32
|
+
subpath (`useHeaderData`, `useFooterData`) — neither was re-exported from the root.
|
|
33
|
+
|
|
34
|
+
3. **Pass `formatDayLabel` if you rely on localized day tabs.** Without it,
|
|
35
|
+
`generateFreeTimeGroups` labels days as `DD.MM`. This affects only free-slot mode —
|
|
36
|
+
in interval mode the day names come from the API.
|
|
37
|
+
|
|
38
|
+
### Added
|
|
39
|
+
|
|
40
|
+
- `check:boundaries` gate that fails the build when Nuxt, Unhead, route policy, or
|
|
41
|
+
tenant presets reappear in `src/`.
|
|
42
|
+
- Pull-request quality checks restored in CI.
|
|
43
|
+
|
|
44
|
+
### Removed
|
|
45
|
+
|
|
46
|
+
- The `./layout` subpath (`useHeaderData`, `useFooterData`, and the `HeaderData`,
|
|
47
|
+
`HeaderDataOptions`, `FooterData`, `FooterDataOptions`, `FormattedPhone`, `LegalLink`
|
|
48
|
+
types) — header and footer composition reads consumer config and belongs to the
|
|
49
|
+
consumer.
|
|
50
|
+
- `catalogRoutes` — catalog route policy is owned by the consumer.
|
|
51
|
+
- `withSeoMetaPriority` — `tagPriority` is Unhead-specific.
|
|
52
|
+
- `THEME_PRESETS`, `DARK_THEME_PRESETS`, `ThemePreset` — tenant branding.
|
|
53
|
+
- `buildSnippetHead`, `SnippetHead` — the head payload shape is framework-specific.
|
|
54
|
+
|
|
55
|
+
### Changed
|
|
56
|
+
|
|
57
|
+
- Storefront runtime now requires a consumer-owned message formatter. Cart notification
|
|
58
|
+
copy is emitted as stable message keys instead of Russian literals. Error text
|
|
59
|
+
forwarded from the API is passed through untouched and stays in the language the
|
|
60
|
+
backend sent. Formatting helpers — weight units, schedule status, contact labels,
|
|
61
|
+
address parsing, pluralization — remain Russian-only and are tracked as known debt.
|
|
62
|
+
- Delivery slot labels are consumer-configurable and default to locale-neutral dates.
|
|
63
|
+
- SEO builders now return framework-neutral meta records without Unhead-specific fields.
|
|
64
|
+
- `@zenky/storefront-api` peer range moved to `^1.0.1`.
|
|
65
|
+
|
|
66
|
+
## 0.10.3 - 2026-07-24
|
|
67
|
+
|
|
68
|
+
### Added
|
|
69
|
+
|
|
70
|
+
- Pull-request CI for formatting, linting, types, coverage, tests, package exports,
|
|
71
|
+
Node/runtime compatibility, bundle budgets, and secret scanning.
|
|
72
|
+
- Dependabot updates for npm dependencies and GitHub Actions.
|
|
73
|
+
- Public security, contribution, conduct, runtime-port, and release documentation.
|
|
74
|
+
- Coverage ratchet and regression tests for checkout state and credential-safe logging.
|
|
75
|
+
- Cart composables for evaluating product restrictions, confirming blocking
|
|
76
|
+
restrictions, and reading variants that remain visible after optimistic updates.
|
|
77
|
+
|
|
78
|
+
### Changed
|
|
79
|
+
|
|
80
|
+
- GitHub Actions are pinned to immutable commits with minimum workflow permissions.
|
|
81
|
+
- QR-code encoding now uses Web Platform APIs and works without Node `Buffer` or browser
|
|
82
|
+
globals, improving Node SSR and edge-runtime compatibility.
|
|
83
|
+
- npm package metadata now includes its homepage, issue tracker, and supported engines.
|
|
84
|
+
|
|
85
|
+
### Fixed
|
|
86
|
+
|
|
87
|
+
- Empty post-checkout orders no longer trigger a minimum-order-price violation.
|
|
88
|
+
|
|
89
|
+
### Security
|
|
90
|
+
|
|
91
|
+
- Cart and checkout errors now pass through recursive redaction before being logged.
|
|
92
|
+
- Direct cart logging no longer emits complete order, credentials, request, or API error
|
|
93
|
+
objects.
|
|
94
|
+
|
|
95
|
+
## 0.10.0 - 2026-07-21
|
|
96
|
+
|
|
97
|
+
### Added
|
|
98
|
+
|
|
99
|
+
- GitHub release workflow for npm OIDC trusted publishing.
|
|
100
|
+
|
|
101
|
+
### Changed
|
|
102
|
+
|
|
103
|
+
- Package renamed to `@zenky/storefront-vue`.
|
|
104
|
+
- Storefront runtime state and cart flows were isolated across Vue applications and SSR
|
|
105
|
+
requests.
|
package/README.md
CHANGED
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
Headless storefront engine for Zenky — Vue 3 + Pinia, no framework lock-in.
|
|
4
4
|
|
|
5
|
+
[](https://github.com/zenky/storefront-vue/actions/workflows/ci.yml)
|
|
6
|
+
[](https://www.npmjs.com/package/@zenky/storefront-vue)
|
|
7
|
+
|
|
5
8
|
One engine behind many storefronts. The cart, order building, checkout, catalog resolution, delivery slots, SEO/JSON-LD, theme, and store/profile state all live here as framework-agnostic composables and Pinia stores. The consumer — a Nuxt site, a QR-code menu, a new template — brings the framework glue (cookies, config, toasts, HTTP transport, `useHead`) and draws its own UI on top.
|
|
6
9
|
|
|
7
10
|
The design is Ports & Adapters: the core declares small ports for everything it needs from the outside world, the consumer provides adapters once, and every composable reads them through `useRuntime()`. The core never imports `useCookie`, `useRoute`, `useHead`, `$fetch`, or anything Nuxt-specific.
|
|
@@ -18,7 +21,7 @@ Peer dependencies (the consumer already has these):
|
|
|
18
21
|
{
|
|
19
22
|
"vue": "^3.5.0",
|
|
20
23
|
"pinia": "^3.0.0",
|
|
21
|
-
"@zenky/storefront-api": "
|
|
24
|
+
"@zenky/storefront-api": "^1.0.1",
|
|
22
25
|
"@zenky/integrations-sdk": ">=0.1.3"
|
|
23
26
|
}
|
|
24
27
|
```
|
|
@@ -45,6 +48,9 @@ app.use(
|
|
|
45
48
|
warning: (m) => toast.warning(m),
|
|
46
49
|
message: (title, opts) => toast(title, opts),
|
|
47
50
|
},
|
|
51
|
+
messages: { // consumer-owned localization
|
|
52
|
+
format: (key, params) => i18n.t(key, params),
|
|
53
|
+
},
|
|
48
54
|
activity: { // busy indicators for long operations
|
|
49
55
|
begin: (kind) => busy.begin(kind),
|
|
50
56
|
end: (kind) => busy.end(kind),
|
|
@@ -69,7 +75,7 @@ cart.totalPrice.value
|
|
|
69
75
|
|
|
70
76
|
## Runtime Ports
|
|
71
77
|
|
|
72
|
-
`createStorefront(runtime)` takes one object.
|
|
78
|
+
`createStorefront(runtime)` takes one object. Six ports are required; the rest are optional — omit an optional port and the feature that needs it is simply skipped.
|
|
73
79
|
|
|
74
80
|
| Port | Required | What the consumer provides |
|
|
75
81
|
| --- | --- | --- |
|
|
@@ -77,6 +83,7 @@ cart.totalPrice.value
|
|
|
77
83
|
| `config` | yes | `{ baseUrl, baseAuthUrl, salesChannelId? }`. |
|
|
78
84
|
| `storage` | yes | Key/value persistence — cookies, `localStorage`, memory. |
|
|
79
85
|
| `notifier` | yes | Toasts: `error` / `success` / `warning` / `message`. |
|
|
86
|
+
| `messages` | yes | Maps stable domain message keys to localized consumer copy. |
|
|
80
87
|
| `activity` | yes | `begin(kind)` / `end(kind)` for busy state. |
|
|
81
88
|
| `events` | no | Lazy `{ get() }` provider for `ZenkyIntegrationsSDK`; resolve on every event. |
|
|
82
89
|
| `realtime` | no | Lazy `{ get() }` provider for the WebSocket adapter (`subscribe` / `unsubscribe` / `isReady`). |
|
|
@@ -90,28 +97,61 @@ Types for every port live in the `ports` subpath, alongside no-op defaults and a
|
|
|
90
97
|
import {
|
|
91
98
|
type StorefrontRuntime,
|
|
92
99
|
type StorageAdapter,
|
|
100
|
+
KEY_MESSAGE_FORMATTER,
|
|
93
101
|
NOOP_NOTIFIER,
|
|
94
102
|
NOOP_ACTIVITY_REPORTER,
|
|
95
103
|
createMemoryStorage,
|
|
96
104
|
} from '@zenky/storefront-vue/ports'
|
|
97
105
|
```
|
|
98
106
|
|
|
107
|
+
The full public contract, adapter examples, SSR lifecycle, and security boundary are in
|
|
108
|
+
[Runtime Ports](docs/ports.md). For a step-by-step consumer integration and upgrade
|
|
109
|
+
checklist, see [Consumer Setup](docs/consumer-setup.md).
|
|
110
|
+
|
|
99
111
|
## Subpath Imports
|
|
100
112
|
|
|
101
113
|
Each public domain is its own entry point, so bundlers only pull in what you import.
|
|
102
114
|
|
|
103
115
|
```ts
|
|
104
116
|
import { minorToMajor } from '@zenky/storefront-vue/money'
|
|
105
|
-
import { buildCssVariableMap
|
|
117
|
+
import { buildCssVariableMap } from '@zenky/storefront-vue/theme'
|
|
106
118
|
import { getRemoteCatalog, findCategoryByShortId } from '@zenky/storefront-vue/catalog'
|
|
107
119
|
import { useStorefrontCart, useCheckoutSubmit } from '@zenky/storefront-vue/cart'
|
|
108
120
|
import { generateFreeTimeGroups } from '@zenky/storefront-vue/order'
|
|
109
121
|
import { buildProductSchema, buildOgTags } from '@zenky/storefront-vue/seo'
|
|
110
|
-
import { useHeaderData, useFooterData } from '@zenky/storefront-vue/layout'
|
|
111
122
|
import { usePaginatedList } from '@zenky/storefront-vue/pagination'
|
|
112
123
|
```
|
|
113
124
|
|
|
114
|
-
Available subpaths: `ports`, `money`, `utils`, `theme`, `stores`, `products`, `catalog`, `cart`, `order`, `promotions`, `seo`, `
|
|
125
|
+
Available subpaths: `ports`, `money`, `utils`, `theme`, `stores`, `products`, `catalog`, `cart`, `order`, `promotions`, `seo`, `pagination`, `snippets`, `website-settings`.
|
|
126
|
+
|
|
127
|
+
Routing, tenant theme presets, localized copy, header/footer composition, and conversion to
|
|
128
|
+
framework-specific head records belong to the consumer. Core SEO builders return plain
|
|
129
|
+
records; a Nuxt adapter may add Unhead-specific fields such as `tagPriority`.
|
|
130
|
+
|
|
131
|
+
## Runtime Compatibility
|
|
132
|
+
|
|
133
|
+
- ESM-only, targeting ES2022.
|
|
134
|
+
- Vue 3.5+ and Pinia 3.
|
|
135
|
+
- Node.js 20.19+ for SSR and package tooling; Node.js 22 is recommended for production and development.
|
|
136
|
+
- Modern browsers and edge runtimes with standard Web Platform APIs.
|
|
137
|
+
|
|
138
|
+
CI imports every public entry in Node SSR and scans the emitted ESM for CommonJS, Node
|
|
139
|
+
built-ins, `Buffer`, and `process`. Browser-only behavior is guarded; for example,
|
|
140
|
+
online-payment retry accepts an explicit `currentUrl` when no `window` is available.
|
|
141
|
+
|
|
142
|
+
For SSR, create a new Vue app, Pinia instance, storefront runtime, and storage adapter per
|
|
143
|
+
request. Never share `createMemoryStorage()` between users.
|
|
144
|
+
|
|
145
|
+
## Package Size
|
|
146
|
+
|
|
147
|
+
Every domain has a tree-shakeable subpath. CI measures the transitive gzip graph for the
|
|
148
|
+
root, cart, and utils entries plus all emitted JavaScript. The budgets are regression
|
|
149
|
+
ceilings, not size targets; increasing one requires review and a release-note explanation.
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
npm run build
|
|
153
|
+
npm run check:size
|
|
154
|
+
```
|
|
115
155
|
|
|
116
156
|
## Pinia Stores
|
|
117
157
|
|
|
@@ -138,9 +178,16 @@ majorToMinor(650, 'RUB') // 65000 — user input back into the store
|
|
|
138
178
|
```bash
|
|
139
179
|
npm run dev # tsup --watch
|
|
140
180
|
npm run build # ESM + .d.ts to dist/
|
|
181
|
+
npm run lint # Biome lint
|
|
182
|
+
npm run format # Biome format --write
|
|
141
183
|
npm run typecheck # tsc --noEmit
|
|
142
184
|
npm test # vitest
|
|
185
|
+
npm run test:coverage # vitest + V8 coverage report
|
|
186
|
+
npm run check # format + lint + types + tests + build + exports
|
|
143
187
|
npm run check:exports # publint + are-the-types-wrong (esm-only profile)
|
|
188
|
+
npm run check:boundaries # reject Nuxt/Unhead and consumer policy in src/
|
|
189
|
+
npm run check:runtime # import all entries in SSR + reject Node-only output
|
|
190
|
+
npm run check:size # enforce gzip bundle budgets
|
|
144
191
|
```
|
|
145
192
|
|
|
146
193
|
### Local linking with yalc
|
|
@@ -165,7 +212,20 @@ npm run build && npx yalc push
|
|
|
165
212
|
- `test` / `test:watch` — run the Vitest suite.
|
|
166
213
|
- `typecheck` — type-only compile.
|
|
167
214
|
- `check:exports` — validate the exports map and published types.
|
|
168
|
-
- `
|
|
215
|
+
- `check:boundaries` — reject Nuxt/Unhead APIs, routes, and tenant presets in core source.
|
|
216
|
+
- `check:runtime` — verify Node SSR imports and browser/edge-safe ESM output.
|
|
217
|
+
- `check:size` — enforce root/domain/all-output gzip budgets.
|
|
218
|
+
- `check:ci` — quality gate with the V8 coverage ratchet.
|
|
219
|
+
- `prepublishOnly` — run the release quality gate.
|
|
220
|
+
|
|
221
|
+
## Contributing and Releases
|
|
222
|
+
|
|
223
|
+
Read [CONTRIBUTING.md](CONTRIBUTING.md) before opening a pull request. User-visible changes
|
|
224
|
+
belong in [CHANGELOG.md](CHANGELOG.md); maintainer steps are documented in the
|
|
225
|
+
[release process](docs/releasing.md).
|
|
226
|
+
|
|
227
|
+
Security vulnerabilities must be reported privately according to
|
|
228
|
+
[SECURITY.md](SECURITY.md), never through a public issue.
|
|
169
229
|
|
|
170
230
|
## License
|
|
171
231
|
|
package/dist/cart/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ProductModifiersRequest, OrderProductVariant, PaymentMethod, OrderPaymentMethodRequest, OrderAuthenticationMethod, OrderCredentials, Order, OrderCheckoutTotal, OrderSettings, OrderPaymentMethod, OrderDeliveryMethod, InclusionRequest, ZenkyStorefront, SetOrderCustomerRequest, SetOrderDeliveryRequest, OrderPromocode, OrderCheckoutResult, RecaptchaAction } from '@zenky/storefront-api';
|
|
1
|
+
import { ProductModifiersRequest, OrderProductVariant, PaymentMethod, OrderPaymentMethodRequest, OrderAuthenticationMethod, OrderCredentials, Order, OrderCheckoutTotal, OrderSettings, OrderPaymentMethod, OrderDeliveryMethod, InclusionRequest, ZenkyStorefront, SetOrderCustomerRequest, SetOrderDeliveryRequest, OrderPromocode, OrderCheckoutResult, RecaptchaAction, EvaluatedRestriction, Media, Product } from '@zenky/storefront-api';
|
|
2
2
|
import { ComputedRef, MaybeRefOrGetter, Ref } from 'vue';
|
|
3
3
|
import { ActivityReporter, Notifier, Result } from '../ports/index.js';
|
|
4
4
|
import '@zenky/integrations-sdk';
|
|
@@ -556,4 +556,33 @@ interface StorefrontCart {
|
|
|
556
556
|
}
|
|
557
557
|
declare function useStorefrontCart(): StorefrontCart;
|
|
558
558
|
|
|
559
|
-
|
|
559
|
+
/** Данные товара для показа в модалке гейта (как строка корзины). */
|
|
560
|
+
interface RestrictionGateProduct {
|
|
561
|
+
name: string;
|
|
562
|
+
image: Media | null;
|
|
563
|
+
}
|
|
564
|
+
interface RestrictionGate {
|
|
565
|
+
isOpen: Ref<boolean>;
|
|
566
|
+
blocking: Ref<EvaluatedRestriction[]>;
|
|
567
|
+
product: Ref<RestrictionGateProduct | null>;
|
|
568
|
+
confirmBlocking: (items: EvaluatedRestriction[], gateProduct: RestrictionGateProduct) => Promise<boolean>;
|
|
569
|
+
confirm: () => void;
|
|
570
|
+
cancel: () => void;
|
|
571
|
+
}
|
|
572
|
+
declare function useRestrictionGate(): RestrictionGate;
|
|
573
|
+
|
|
574
|
+
type RestrictedProduct = Pick<Product, 'id' | 'restrictions' | 'name' | 'images'>;
|
|
575
|
+
interface RestrictedAddToCart {
|
|
576
|
+
checkRestrictionsAllowed: (product: RestrictedProduct, alreadyInCart: boolean) => Promise<boolean>;
|
|
577
|
+
addWithRestrictionCheck: (product: RestrictedProduct, request: CartItemRequest, alreadyInCart: boolean) => Promise<void>;
|
|
578
|
+
}
|
|
579
|
+
declare function useRestrictedAddToCart(): RestrictedAddToCart;
|
|
580
|
+
|
|
581
|
+
/**
|
|
582
|
+
* Позиции корзины, видимые покупателю: серверное количество с учётом оптимистичной дельты.
|
|
583
|
+
* Единый источник для списка, футера и подсветки — иначе блокировка чекаута, поиск
|
|
584
|
+
* блокирующей позиции и реальный рендер списка могут разъехаться.
|
|
585
|
+
*/
|
|
586
|
+
declare function useVisibleCartVariants(): ComputedRef<OrderProductVariant[]>;
|
|
587
|
+
|
|
588
|
+
export { type AttachedCustomerCache, type BonusesReconciliation, type BonusesReconciliationDeps, CASH_DENOMINATIONS_MAJOR, type CachedCustomerView, type CartCredentials, type CartDependencies, type CartErrorScope, type CartInitialization, type CartItemRequest, type CartLineKeyParams, type CartMutationComposable, type CartOperations, type CartQuantities, type CartRecalculation, type CartRecalculationDeps, type CartStockWatcher, type CashChangePresetsOptions, type CheckoutFlowFlags, type CheckoutSubmitComposable, type CustomerAttachComposable, DEFAULT_ROUND_STEPS_MAJOR, type MainPaymentRequestParams, type MutationKind, type MutationOptions, ORDER_EVENTS, ORDER_WITH, type OrderBonusesComposable, type OrderBonusesDeps, type OrderCredentialsLike, type OrderDelivery, type OrderDeliveryDeps, type OrderPromocodeComposable, type OrderPromocodeDeps, type OrderSettingsComposable, type OrderTotal, type PaymentSelection, type PaymentSelectionComposable, type RecaptchaPayloadProvider, type RestrictedAddToCart, type RestrictionGate, type RestrictionGateProduct, type RetryOptions, type StorefrontCart, buildCartLineKey, buildCashChangePresets, buildMainPaymentRequest, getCartErrorCode, getCartErrorHttpCode, getCartErrorMessage, getCashDenominationsMinor, getDefaultRoundStepsMinor, getValidationErrors, logCartError, normalizeAddress, useBonusesReconciliation, useCartAddressSync, useCartCredentials, useCartCustomerAttachment, useCartDeliveryAttachment, useCartInitialization, useCartMutation, useCartOperations, useCartQuantities, useCartRecalculation, useCartStockWatcher, useCheckoutFlow, useCheckoutSubmit, useCustomerAttach, useOnlinePaymentRetry, useOrderBonuses, useOrderChannel, useOrderDelivery, useOrderPromocode, useOrderSettings, useOrderTotal, usePaymentSelection, useRestrictedAddToCart, useRestrictionGate, useStorefrontCart, useVisibleCartVariants, variantLineKey };
|
package/dist/cart/index.js
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
export { CASH_DENOMINATIONS_MAJOR, DEFAULT_ROUND_STEPS_MAJOR, ORDER_EVENTS, ORDER_WITH, buildCartLineKey, buildCashChangePresets, buildMainPaymentRequest, getCartErrorCode, getCartErrorHttpCode, getCartErrorMessage, getCashDenominationsMinor, getDefaultRoundStepsMinor, getValidationErrors, logCartError, normalizeAddress, useBonusesReconciliation, useCartAddressSync, useCartCustomerAttachment, useCartDeliveryAttachment, useCartInitialization, useCartMutation, useCartOperations, useCartQuantities, useCartRecalculation, useCartStockWatcher, useCheckoutFlow, useCheckoutSubmit, useCustomerAttach, useOnlinePaymentRetry, useOrderBonuses, useOrderChannel, useOrderDelivery, useOrderPromocode, useOrderSettings, useOrderTotal, usePaymentSelection, useStorefrontCart, variantLineKey } from '../chunk-
|
|
2
|
-
export { useCartCredentials } from '../chunk-
|
|
3
|
-
import '../chunk-5QCUH3FF.js';
|
|
1
|
+
export { CASH_DENOMINATIONS_MAJOR, DEFAULT_ROUND_STEPS_MAJOR, ORDER_EVENTS, ORDER_WITH, buildCartLineKey, buildCashChangePresets, buildMainPaymentRequest, getCartErrorCode, getCartErrorHttpCode, getCartErrorMessage, getCashDenominationsMinor, getDefaultRoundStepsMinor, getValidationErrors, logCartError, normalizeAddress, useBonusesReconciliation, useCartAddressSync, useCartCustomerAttachment, useCartDeliveryAttachment, useCartInitialization, useCartMutation, useCartOperations, useCartQuantities, useCartRecalculation, useCartStockWatcher, useCheckoutFlow, useCheckoutSubmit, useCustomerAttach, useOnlinePaymentRetry, useOrderBonuses, useOrderChannel, useOrderDelivery, useOrderPromocode, useOrderSettings, useOrderTotal, usePaymentSelection, useRestrictedAddToCart, useRestrictionGate, useStorefrontCart, useVisibleCartVariants, variantLineKey } from '../chunk-YS5DXYYV.js';
|
|
2
|
+
export { useCartCredentials } from '../chunk-YREGCQSB.js';
|
|
4
3
|
import '../chunk-Z3IW4ODZ.js';
|
|
5
|
-
import '../chunk-
|
|
6
|
-
import '../chunk-
|
|
7
|
-
import '../chunk-EYRCAUUP.js';
|
|
8
|
-
import '../chunk-VL3T36VM.js';
|
|
9
|
-
import '../chunk-V3VVDQIR.js';
|
|
4
|
+
import '../chunk-NIQFYJRP.js';
|
|
5
|
+
import '../chunk-E3G7NGCH.js';
|
|
10
6
|
import '../chunk-RO25KNM5.js';
|
|
11
|
-
import '../chunk-
|
|
7
|
+
import '../chunk-5QCUH3FF.js';
|
|
8
|
+
import '../chunk-TB5TBJ4U.js';
|
|
12
9
|
//# sourceMappingURL=index.js.map
|
|
13
10
|
//# sourceMappingURL=index.js.map
|
package/dist/catalog/index.d.ts
CHANGED
|
@@ -60,14 +60,4 @@ declare function useCollections(sdk: ZenkyStorefront): {
|
|
|
60
60
|
loadCollections: (storeId: string, request?: CollectionsListRequest) => Promise<ProductsCollection[]>;
|
|
61
61
|
};
|
|
62
62
|
|
|
63
|
-
|
|
64
|
-
declare const catalogRoutes: {
|
|
65
|
-
/** Корневая страница каталога: список категорий + коллекций */
|
|
66
|
-
readonly index: () => string;
|
|
67
|
-
/** Страница конкретной категории */
|
|
68
|
-
readonly category: (shortId: string, slug: string | null) => string;
|
|
69
|
-
/** Страница конкретной коллекции */
|
|
70
|
-
readonly collection: (id: string) => string;
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
export { type GroupedProducts, type SubcategoryGroup, catalogRoutes, collectDescendantIds, findCategoryById, findCategoryByShortId, findRootAncestor, getCategoryPath, getCity, getRemoteCatalog, getStock, groupProductsBySubcategory, useCollections };
|
|
63
|
+
export { type GroupedProducts, type SubcategoryGroup, collectDescendantIds, findCategoryById, findCategoryByShortId, findRootAncestor, getCategoryPath, getCity, getRemoteCatalog, getStock, groupProductsBySubcategory, useCollections };
|
package/dist/catalog/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export { getCity, getRemoteCatalog, getStock } from '../chunk-
|
|
1
|
+
export { collectDescendantIds, findCategoryById, findCategoryByShortId, findRootAncestor, getCategoryPath, groupProductsBySubcategory, useCollections } from '../chunk-NG7RUIWW.js';
|
|
2
|
+
export { getCity, getRemoteCatalog, getStock } from '../chunk-E3G7NGCH.js';
|
|
3
3
|
//# sourceMappingURL=index.js.map
|
|
4
4
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// src/snippets/snippets.ts
|
|
2
|
+
function normalizeSnippets(groups) {
|
|
3
|
+
if (!Array.isArray(groups)) return [];
|
|
4
|
+
return groups.flatMap(
|
|
5
|
+
(group, groupIndex) => (group.snippets ?? []).filter((item) => !!item.content?.trim()).map((item, itemIndex) => {
|
|
6
|
+
const snippet = {
|
|
7
|
+
id: `${group.region}-${groupIndex}-${itemIndex}`,
|
|
8
|
+
position: group.region,
|
|
9
|
+
language: item.language,
|
|
10
|
+
code: item.content,
|
|
11
|
+
enabled: item.enabled ?? true
|
|
12
|
+
};
|
|
13
|
+
if (item.name !== void 0) snippet.name = item.name;
|
|
14
|
+
return snippet;
|
|
15
|
+
})
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export { normalizeSnippets };
|
|
20
|
+
//# sourceMappingURL=chunk-2CI4RW7V.js.map
|
|
21
|
+
//# sourceMappingURL=chunk-2CI4RW7V.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/snippets/snippets.ts"],"names":[],"mappings":";AAwBO,SAAS,kBAAkB,MAAA,EAAsD;AACpF,EAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,MAAM,CAAA,SAAU,EAAC;AAEpC,EAAA,OAAO,MAAA,CAAO,OAAA;AAAA,IAAQ,CAAC,OAAO,UAAA,KAAA,CACzB,KAAA,CAAM,YAAY,EAAC,EACf,OAAO,CAAC,IAAA,KAAS,CAAC,CAAC,IAAA,CAAK,SAAS,IAAA,EAAM,EACvC,GAAA,CAAI,CAAC,MAAM,SAAA,KAAuB;AAC/B,MAAA,MAAM,OAAA,GAAmB;AAAA,QACrB,IAAI,CAAA,EAAG,KAAA,CAAM,MAAM,CAAA,CAAA,EAAI,UAAU,IAAI,SAAS,CAAA,CAAA;AAAA,QAC9C,UAAU,KAAA,CAAM,MAAA;AAAA,QAChB,UAAU,IAAA,CAAK,QAAA;AAAA,QACf,MAAM,IAAA,CAAK,OAAA;AAAA,QACX,OAAA,EAAS,KAAK,OAAA,IAAW;AAAA,OAC7B;AAEA,MAAA,IAAI,IAAA,CAAK,IAAA,KAAS,MAAA,EAAW,OAAA,CAAQ,OAAO,IAAA,CAAK,IAAA;AACjD,MAAA,OAAO,OAAA;AAAA,IACX,CAAC;AAAA,GACT;AACJ","file":"chunk-2CI4RW7V.js","sourcesContent":["export type SnippetPosition = 'head_start' | 'head_end' | 'body_start' | 'body_end'\nexport type SnippetLanguage = 'html' | 'css' | 'javascript'\n\nexport interface Snippet {\n id: string\n name?: string\n position: SnippetPosition\n language: SnippetLanguage\n code: string\n enabled: boolean\n}\n\nexport interface RawSnippetItem {\n language: SnippetLanguage\n content: string\n enabled?: boolean\n name?: string\n}\n\nexport interface SnippetGroup {\n region: SnippetPosition\n snippets: RawSnippetItem[]\n}\n\nexport function normalizeSnippets(groups: SnippetGroup[] | null | undefined): Snippet[] {\n if (!Array.isArray(groups)) return []\n\n return groups.flatMap((group, groupIndex) =>\n (group.snippets ?? [])\n .filter((item) => !!item.content?.trim())\n .map((item, itemIndex): Snippet => {\n const snippet: Snippet = {\n id: `${group.region}-${groupIndex}-${itemIndex}`,\n position: group.region,\n language: item.language,\n code: item.content,\n enabled: item.enabled ?? true,\n }\n // exactOptionalPropertyTypes: name задаём только если оно есть\n if (item.name !== undefined) snippet.name = item.name\n return snippet\n })\n )\n}\n"]}
|
|
@@ -212,116 +212,6 @@ function useTheme(colorConfig, fontConfig) {
|
|
|
212
212
|
};
|
|
213
213
|
}
|
|
214
214
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
id: "yarollov",
|
|
219
|
-
label: "Yarollov",
|
|
220
|
-
description: "\u0424\u0438\u0440\u043C\u0435\u043D\u043D\u044B\u0439 \u0431\u0440\u0435\u043D\u0434 \u2014 \u043C\u0430\u043B\u0438\u043D\u043E\u0432\u044B\u0439 primary, \u0442\u0451\u043C\u043D\u043E-\u0441\u0438\u043D\u0438\u0439 accent",
|
|
221
|
-
colors: {
|
|
222
|
-
primary: "#D81C4B",
|
|
223
|
-
secondary: "#8272C1",
|
|
224
|
-
accent: "#1E1B4B",
|
|
225
|
-
background: "#FFFFFF",
|
|
226
|
-
text: "#1A1A1A"
|
|
227
|
-
}
|
|
228
|
-
},
|
|
229
|
-
{
|
|
230
|
-
id: "orange",
|
|
231
|
-
label: "Orange",
|
|
232
|
-
description: "\u0422\u0451\u043F\u043B\u044B\u0439 \u043E\u0440\u0430\u043D\u0436\u0435\u0432\u044B\u0439 \u0441 \u0441\u0438\u043D\u0438\u043C \u0430\u043A\u0446\u0435\u043D\u0442\u043E\u043C",
|
|
233
|
-
colors: {
|
|
234
|
-
primary: "#FE5000",
|
|
235
|
-
secondary: "#64748B",
|
|
236
|
-
accent: "#007AFF",
|
|
237
|
-
background: "#FFFFFF",
|
|
238
|
-
text: "#1A1A1A"
|
|
239
|
-
}
|
|
240
|
-
},
|
|
241
|
-
{
|
|
242
|
-
id: "sushi03",
|
|
243
|
-
label: "Sushi03",
|
|
244
|
-
description: "\u0422\u0451\u043C\u043D\u043E-\u0441\u0438\u043D\u0438\u0439 primary + \u0433\u043E\u0440\u0447\u0438\u0447\u043D\u044B\u0439 accent",
|
|
245
|
-
colors: {
|
|
246
|
-
primary: "#002F8C",
|
|
247
|
-
secondary: "#8B9DC3",
|
|
248
|
-
accent: "#FFDE69",
|
|
249
|
-
background: "#FFFFFF",
|
|
250
|
-
text: "#1A1A1A",
|
|
251
|
-
success: "#00A980",
|
|
252
|
-
danger: "#E61717"
|
|
253
|
-
}
|
|
254
|
-
},
|
|
255
|
-
{
|
|
256
|
-
id: "olive",
|
|
257
|
-
label: "Olive Whisper",
|
|
258
|
-
description: "\u041A\u0438\u0441\u043B\u043E\u0442\u043D\u043E-\u0437\u0435\u043B\u0451\u043D\u044B\u0439 \u043D\u0430 \u0442\u0451\u043C\u043D\u043E\u043C \u0444\u043E\u043D\u0435",
|
|
259
|
-
colors: {
|
|
260
|
-
primary: "#C0F53D",
|
|
261
|
-
secondary: "#0A0D04",
|
|
262
|
-
accent: "#C0F53D",
|
|
263
|
-
background: "#1A2209",
|
|
264
|
-
text: "#FAFFF3",
|
|
265
|
-
headerBg: "#1A2209",
|
|
266
|
-
footerBg: "#0A0D04",
|
|
267
|
-
footerText: "#FAFFF3",
|
|
268
|
-
footerTextMuted: "#6B7A4A"
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
];
|
|
272
|
-
var DARK_THEME_PRESETS = [
|
|
273
|
-
{
|
|
274
|
-
id: "yarollov-dark",
|
|
275
|
-
label: "Yarollov Dark",
|
|
276
|
-
description: "\u0424\u0438\u0440\u043C\u0435\u043D\u043D\u044B\u0439 \u0431\u0440\u0435\u043D\u0434 (\u0442\u0451\u043C\u043D\u0430\u044F)",
|
|
277
|
-
colors: {
|
|
278
|
-
primary: "#F472B6",
|
|
279
|
-
secondary: "#A78BFA",
|
|
280
|
-
accent: "#818CF8",
|
|
281
|
-
background: "#121212",
|
|
282
|
-
text: "#E5E5E5",
|
|
283
|
-
headerBg: "#1A1A1A",
|
|
284
|
-
footerBg: "#0F0F0F",
|
|
285
|
-
footerText: "#A3A3A3",
|
|
286
|
-
footerTextMuted: "#525252"
|
|
287
|
-
}
|
|
288
|
-
},
|
|
289
|
-
{
|
|
290
|
-
id: "orange-dark",
|
|
291
|
-
label: "Orange Dark",
|
|
292
|
-
description: "\u0422\u0451\u043F\u043B\u044B\u0439 \u043E\u0440\u0430\u043D\u0436\u0435\u0432\u044B\u0439 (\u0442\u0451\u043C\u043D\u0430\u044F)",
|
|
293
|
-
colors: {
|
|
294
|
-
primary: "#FE5000",
|
|
295
|
-
secondary: "#64748B",
|
|
296
|
-
accent: "#60A5FA",
|
|
297
|
-
background: "#121212",
|
|
298
|
-
text: "#E5E5E5",
|
|
299
|
-
headerBg: "#1A1A1A",
|
|
300
|
-
footerBg: "#0F0F0F",
|
|
301
|
-
footerText: "#A3A3A3",
|
|
302
|
-
footerTextMuted: "#525252"
|
|
303
|
-
}
|
|
304
|
-
},
|
|
305
|
-
{
|
|
306
|
-
id: "sushi03-dark",
|
|
307
|
-
label: "Sushi03 Dark",
|
|
308
|
-
description: "\u0422\u0451\u043C\u043D\u043E-\u0441\u0438\u043D\u0438\u0439 (\u0442\u0451\u043C\u043D\u0430\u044F)",
|
|
309
|
-
colors: {
|
|
310
|
-
primary: "#4D8DE8",
|
|
311
|
-
secondary: "#5A6D8A",
|
|
312
|
-
accent: "#FFDE69",
|
|
313
|
-
background: "#0F1419",
|
|
314
|
-
text: "#E5E5E5",
|
|
315
|
-
success: "#34D399",
|
|
316
|
-
danger: "#F87171",
|
|
317
|
-
headerBg: "#161C24",
|
|
318
|
-
footerBg: "#0A0F14",
|
|
319
|
-
footerText: "#94A3B8",
|
|
320
|
-
footerTextMuted: "#475569"
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
];
|
|
324
|
-
|
|
325
|
-
export { DARK_THEME_PRESETS, THEME_PRESETS, buildCssVariableMap, generatePrimaryShades, generateShades, useTheme };
|
|
326
|
-
//# sourceMappingURL=chunk-GW2QNTAD.js.map
|
|
327
|
-
//# sourceMappingURL=chunk-GW2QNTAD.js.map
|
|
215
|
+
export { buildCssVariableMap, generatePrimaryShades, generateShades, useTheme };
|
|
216
|
+
//# sourceMappingURL=chunk-4IFPVEO7.js.map
|
|
217
|
+
//# sourceMappingURL=chunk-4IFPVEO7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/theme/colors.ts","../src/theme/useTheme.ts"],"names":["p","q"],"mappings":"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","file":"chunk-4IFPVEO7.js","sourcesContent":["// Генерация цветовой шкалы и CSS-переменных из базовых цветов бренда.\n// Чистая математика в HSL/RGB — ноль зависимостей, ноль Nuxt. Портируется как есть.\n\nexport interface ThemeColorConfig {\n primary: string\n secondary: string\n accent: string\n background: string\n text: string\n success?: string\n danger?: string\n warning?: string\n info?: string\n /** Цвет текста поверх primary-фона. Если не задан — рассчитывается автоматически. */\n onPrimary?: string\n headerBg?: string\n footerBg?: string\n footerText?: string\n footerTextMuted?: string\n}\n\ninterface HslColor {\n h: number\n s: number\n l: number\n}\n\nfunction hexToHsl(hex: string): HslColor {\n const clean = hex.replace('#', '')\n const r = parseInt(clean.substring(0, 2), 16) / 255\n const g = parseInt(clean.substring(2, 4), 16) / 255\n const b = parseInt(clean.substring(4, 6), 16) / 255\n\n const max = Math.max(r, g, b)\n const min = Math.min(r, g, b)\n const l = (max + min) / 2\n\n if (max === min) {\n return { h: 0, s: 0, l }\n }\n\n const d = max - min\n const s = l > 0.5 ? d / (2 - max - min) : d / (max + min)\n\n let h = 0\n\n if (max === r) {\n h = ((g - b) / d + (g < b ? 6 : 0)) / 6\n } else if (max === g) {\n h = ((b - r) / d + 2) / 6\n } else {\n h = ((r - g) / d + 4) / 6\n }\n\n return { h, s, l }\n}\n\nfunction hslToHex(hsl: HslColor): string {\n const { h, s, l } = hsl\n\n if (s === 0) {\n const v = Math.round(l * 255)\n return `#${v.toString(16).padStart(2, '0').repeat(3)}`\n }\n\n const hue2rgb = (p: number, q: number, t: number): number => {\n let tt = t\n\n if (tt < 0) tt += 1\n if (tt > 1) tt -= 1\n if (tt < 1 / 6) return p + (q - p) * 6 * tt\n if (tt < 1 / 2) return q\n if (tt < 2 / 3) return p + (q - p) * (2 / 3 - tt) * 6\n\n return p\n }\n\n const q = l < 0.5 ? l * (1 + s) : l + s - l * s\n const p = 2 * l - q\n\n const r = Math.round(hue2rgb(p, q, h + 1 / 3) * 255)\n const g = Math.round(hue2rgb(p, q, h) * 255)\n const b = Math.round(hue2rgb(p, q, h - 1 / 3) * 255)\n\n return `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`\n}\n\n// ---------------------------------------------------------------------------\n// Color utilities\n// ---------------------------------------------------------------------------\n\n/**\n * Mix two hex colors in HSL space.\n * amount: 0 = pure hex1, 100 = pure hex2.\n */\nfunction mixColors(hex1: string, hex2: string, amount: number): string {\n const c1 = hexToHsl(hex1)\n const c2 = hexToHsl(hex2)\n const t = amount / 100\n\n // Handle achromatic mixing: if one color has no saturation,\n // inherit hue from the other\n let h: number\n if (c1.s === 0 && c2.s === 0) {\n h = 0\n } else if (c1.s === 0) {\n h = c2.h\n } else if (c2.s === 0) {\n h = c1.h\n } else {\n // Shortest path around the hue circle\n let dh = c2.h - c1.h\n if (dh > 0.5) dh -= 1\n if (dh < -0.5) dh += 1\n h = c1.h + dh * t\n if (h < 0) h += 1\n if (h > 1) h -= 1\n }\n\n return hslToHex({\n h,\n s: c1.s + (c2.s - c1.s) * t,\n l: c1.l + (c2.l - c1.l) * t,\n })\n}\n\n/**\n * Mix two hex colors in linear RGB space — matches CSS `linear-gradient` overlay behavior.\n * amount: 0 = pure hex1, 100 = pure hex2.\n */\nfunction mixColorsRgb(hex1: string, hex2: string, amount: number): string {\n const c1 = hex1.replace('#', '')\n const c2 = hex2.replace('#', '')\n const t = amount / 100\n\n const r1 = parseInt(c1.substring(0, 2), 16)\n const g1 = parseInt(c1.substring(2, 4), 16)\n const b1 = parseInt(c1.substring(4, 6), 16)\n const r2 = parseInt(c2.substring(0, 2), 16)\n const g2 = parseInt(c2.substring(2, 4), 16)\n const b2 = parseInt(c2.substring(4, 6), 16)\n\n const r = Math.round(r1 + (r2 - r1) * t)\n const g = Math.round(g1 + (g2 - g1) * t)\n const b = Math.round(b1 + (b2 - b1) * t)\n\n return `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`\n}\n\n/**\n * Adjust lightness of a hex color by a relative percentage.\n * delta: -0.05 = 5% darker, +0.05 = 5% lighter.\n */\nfunction adjustLightness(hex: string, delta: number): string {\n const hsl = hexToHsl(hex)\n return hslToHex({\n h: hsl.h,\n s: hsl.s,\n l: Math.min(1, Math.max(0, hsl.l + delta)),\n })\n}\n\n/**\n * Returns a contrasting text color (white or dark) for a given background hex.\n * Uses relative luminance formula (WCAG).\n */\nfunction getContrastColor(hex: string): string {\n const clean = hex.replace('#', '')\n const r = parseInt(clean.substring(0, 2), 16) / 255\n const g = parseInt(clean.substring(2, 4), 16) / 255\n const b = parseInt(clean.substring(4, 6), 16) / 255\n\n // sRGB to linear\n const toLinear = (c: number): number =>\n c <= 0.03928 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4\n const luminance = 0.2126 * toLinear(r) + 0.7152 * toLinear(g) + 0.0722 * toLinear(b)\n\n return luminance > 0.4 ? '#1a1a1a' : '#ffffff'\n}\n\n// ---------------------------------------------------------------------------\n// Primary shades\n// ---------------------------------------------------------------------------\n\nexport interface PrimaryShades {\n lightest: string\n lighter: string\n light: string\n base: string\n dark: string\n darker: string\n darkest: string\n tint: string\n tintHover: string\n tintPressed: string\n ink: string\n}\n\n/** Универсальный генератор 11-ступенчатой шкалы от одного hex. */\nexport function generateShades(\n hex: string,\n bg: string = '#ffffff',\n text: string = '#000000'\n): PrimaryShades {\n return generatePrimaryShades(hex, bg, text)\n}\n\nexport function generatePrimaryShades(\n hex: string,\n bg: string = '#ffffff',\n text: string = '#000000'\n): PrimaryShades {\n const hsl = hexToHsl(hex)\n\n const clamp = (v: number): number => Math.min(1, Math.max(0, v))\n\n // For very dark colors (l < 0.15), dark shades go UP (lighten)\n // because you can't darken black — multiplying 0 by anything stays 0\n const isVeryDark = hsl.l < 0.15\n const dark = isVeryDark ? clamp(hsl.l + 0.12) : clamp(hsl.l * 0.85)\n const darker = isVeryDark ? clamp(hsl.l + 0.08) : clamp(hsl.l * 0.65)\n const darkest = isVeryDark ? clamp(hsl.l + 0.05) : clamp(hsl.l * 0.45)\n\n return {\n lightest: hslToHex({ h: hsl.h, s: hsl.s * 0.3, l: clamp(0.92) }),\n lighter: hslToHex({ h: hsl.h, s: hsl.s * 0.5, l: clamp(0.8) }),\n light: hslToHex({ h: hsl.h, s: hsl.s * 0.7, l: clamp(hsl.l + (1 - hsl.l) * 0.4) }),\n base: hex,\n dark: hslToHex({ h: hsl.h, s: hsl.s, l: dark }),\n darker: hslToHex({ h: hsl.h, s: hsl.s, l: darker }),\n darkest: hslToHex({ h: hsl.h, s: hsl.s, l: darkest }),\n tint: mixColorsRgb(bg, hex, 14),\n tintHover: mixColorsRgb(mixColorsRgb(bg, hex, 14), bg, 34),\n tintPressed: mixColorsRgb(bg, hex, 5),\n ink: mixColorsRgb(text, hex, 44),\n }\n}\n\n// ---------------------------------------------------------------------------\n// Build complete CSS variable map from core colors\n// ---------------------------------------------------------------------------\n\nexport function buildCssVariableMap(config: ThemeColorConfig): Record<string, string> {\n const bg = config.background\n const text = config.text\n const shades = generatePrimaryShades(config.primary, bg, text)\n const secondaryShades = generateShades(config.secondary, bg, text)\n\n const vars: Record<string, string> = {\n // Primary palette\n '--zenky-primary-lightest': shades.lightest,\n '--zenky-primary-lighter': shades.lighter,\n '--zenky-primary-light': shades.light,\n '--zenky-primary': shades.base,\n '--zenky-primary-dark': shades.dark,\n '--zenky-primary-darker': shades.darker,\n '--zenky-primary-darkest': shades.darkest,\n '--zenky-primary-tint': shades.tint,\n '--zenky-primary-tint-hover': shades.tintHover,\n '--zenky-primary-tint-pressed': shades.tintPressed,\n '--zenky-primary-ink': shades.ink,\n\n // Secondary palette\n '--zenky-secondary-lightest': secondaryShades.lightest,\n '--zenky-secondary-lighter': secondaryShades.lighter,\n '--zenky-secondary-light': secondaryShades.light,\n '--zenky-secondary': secondaryShades.base,\n '--zenky-secondary-dark': secondaryShades.dark,\n '--zenky-secondary-darker': secondaryShades.darker,\n '--zenky-secondary-darkest': secondaryShades.darkest,\n\n // Auto-contrast for secondary\n '--zenky-on-secondary': getContrastColor(config.secondary),\n\n // Accent\n '--zenky-accent': config.accent,\n '--zenky-accent-tint': mixColorsRgb(bg, config.accent, 14),\n '--zenky-accent-tint-hover': mixColorsRgb(mixColorsRgb(bg, config.accent, 14), bg, 34),\n '--zenky-accent-tint-pressed': mixColorsRgb(bg, config.accent, 5),\n '--zenky-accent-ink': mixColorsRgb(text, config.accent, 44),\n '--zenky-bg': bg,\n '--zenky-text': text,\n\n // Цвет текста поверх primary: ручная настройка или авто-контраст\n '--zenky-on-primary': config.onPrimary || getContrastColor(config.primary),\n '--zenky-on-accent': getContrastColor(config.accent),\n\n // Derived text shades\n '--zenky-text-muted': mixColors(bg, text, 50),\n '--zenky-text-light': mixColors(bg, text, 35),\n\n // Derived borders\n '--zenky-border-light': mixColors(bg, text, 6),\n '--zenky-border': mixColors(bg, text, 12),\n '--zenky-border-strong': mixColors(bg, text, 35),\n\n // Derived surfaces\n '--zenky-surface-secondary': mixColors(bg, text, 5),\n '--zenky-surface-secondary-hover': mixColors(bg, text, 10),\n '--zenky-surface-active': mixColors(bg, config.primary, 8),\n '--zenky-surface-dark':\n getContrastColor(bg) === '#ffffff'\n ? adjustLightness(bg, 0.08)\n : adjustLightness(text, -0.1),\n '--zenky-control-active': mixColors(bg, text, 80),\n '--zenky-surface-elevated': adjustLightness(bg, 0.06),\n\n // Status (defaults if not provided)\n '--zenky-success': config.success ?? '#22c55e',\n '--zenky-danger': config.danger ?? '#ef4444',\n '--zenky-warning': config.warning ?? '#f59e0b',\n '--zenky-info': config.info ?? '#3b82f6',\n\n // Component semantic (auto-derived with optional overrides)\n '--zenky-header-bg': config.headerBg ?? adjustLightness(bg, -0.02),\n '--zenky-nav-bg': config.headerBg ?? adjustLightness(bg, -0.02),\n '--zenky-footer-bg': config.footerBg ?? adjustLightness(bg, -0.03),\n '--zenky-footer-text': config.footerText ?? mixColors(bg, text, 70),\n '--zenky-footer-text-muted': config.footerTextMuted ?? mixColors(bg, text, 40),\n }\n\n return vars\n}\n","import { computed, type ComputedRef } from 'vue'\n\nimport { buildCssVariableMap, type ThemeColorConfig } from './colors'\n\nexport interface FontConfig {\n family: string\n url: string\n}\n\nexport interface ThemeData {\n cssVariables: ComputedRef<Record<string, string>>\n fontFamily: ComputedRef<string | null>\n fontUrl: ComputedRef<string | null>\n}\n\n/** CSS-переменные темы + шрифт из цвето-/шрифто-конфига (инъекция в head — на стороне app). */\nexport function useTheme(colorConfig: ThemeColorConfig, fontConfig: FontConfig): ThemeData {\n const cssVariables = computed<Record<string, string>>(() => {\n const vars = buildCssVariableMap(colorConfig)\n\n if (fontConfig.family) {\n const stack = `'${fontConfig.family}', system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif`\n vars['--zenky-font-sans'] = stack\n }\n\n return vars\n })\n\n const fontFamily = computed<string | null>(() => fontConfig.family || null)\n const fontUrl = computed<string | null>(() => fontConfig.url || null)\n\n return {\n cssVariables,\n fontFamily,\n fontUrl,\n }\n}\n"]}
|
|
@@ -41,5 +41,5 @@ function getRemoteCatalog(store, city, stock) {
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
export { getCity, getRemoteCatalog, getStock };
|
|
44
|
-
//# sourceMappingURL=chunk-
|
|
45
|
-
//# sourceMappingURL=chunk-
|
|
44
|
+
//# sourceMappingURL=chunk-E3G7NGCH.js.map
|
|
45
|
+
//# sourceMappingURL=chunk-E3G7NGCH.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/catalog/catalogResolver.ts"],"names":[],"mappings":";AAEO,SAAS,OAAA,CAAQ,OAAc,MAAA,EAAqC;AACvE,EAAA,IAAI,CAAC,KAAA,CAAM,MAAA,CAAO,MAAA,EAAQ,OAAO,IAAA;AAEjC,EAAA,MAAM,WAAA,GAAc,KAAA,CAAM,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,UAAU,CAAA,IAAK,KAAA,CAAM,MAAA,CAAO,CAAC,CAAA,IAAK,IAAA;AAEjF,EAAA,IAAI,CAAC,QAAQ,OAAO,WAAA;AAEpB,EAAA,OAAO,KAAA,CAAM,OAAO,IAAA,CAAK,CAAC,MAAM,CAAA,CAAE,EAAA,KAAO,MAAM,CAAA,IAAK,WAAA;AACxD;AAEO,SAAS,QAAA,CAAS,MAAY,OAAA,EAAuC;AACxE,EAAA,IAAI,CAAC,IAAA,CAAK,MAAA,EAAQ,MAAA,EAAQ,OAAO,IAAA;AAEjC,EAAA,MAAM,YAAA,GAAe,IAAA,CAAK,MAAA,CAAO,CAAC,CAAA,IAAK,IAAA;AAEvC,EAAA,IAAI,CAAC,SAAS,OAAO,YAAA;AAErB,EAAA,OAAO,IAAA,CAAK,OAAO,IAAA,CAAK,CAAC,MAAM,CAAA,CAAE,EAAA,KAAO,OAAO,CAAA,IAAK,YAAA;AACxD;AAEO,SAAS,gBAAA,CACZ,KAAA,EACA,IAAA,EACA,KAAA,EACoB;AACpB,EAAA,IAAI,CAAC,KAAA,CAAM,QAAA,CAAS,MAAA,EAAQ;AACxB,IAAA,OAAA,CAAQ,KAAK,4CAAA,EAA8C;AAAA,MACvD,SAAS,KAAA,CAAM,EAAA;AAAA,MACf,QAAQ,IAAA,CAAK,EAAA;AAAA,MACb,OAAA,EAAS,OAAO,EAAA,IAAM;AAAA,KACzB,CAAA;AACD,IAAA,OAAO,IAAA;AAAA,EACX;AAGA,EAAA,IAAI,KAAA,EAAO;AACP,IAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,QAAA,CAAS,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,OAAA,KAAY,IAAA,CAAK,EAAA,IAAM,CAAA,CAAE,QAAA,KAAa,MAAM,EAAE,CAAA;AACzF,IAAA,IAAI,OAAO,OAAO,KAAA;AAAA,EACtB;AAEA,EAAA,MAAM,QAAA,GAAW,KAAA,CAAM,QAAA,CAAS,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,OAAA,KAAY,IAAA,CAAK,EAAA,IAAM,CAAA,CAAE,QAAA,KAAa,IAAI,CAAA;AACxF,EAAA,IAAI,UAAU,OAAO,QAAA;AAErB,EAAA,MAAM,MAAA,GAAS,KAAA,CAAM,QAAA,CAAS,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,OAAA,KAAY,IAAA,IAAQ,CAAA,CAAE,QAAA,KAAa,IAAI,CAAA;AACnF,EAAA,IAAI,QAAQ,OAAO,MAAA;AAEnB,EAAA,OAAA,CAAQ,KAAK,gEAAA,EAAkE;AAAA,IAC3E,SAAS,KAAA,CAAM,EAAA;AAAA,IACf,QAAQ,IAAA,CAAK,EAAA;AAAA,IACb,OAAA,EAAS,OAAO,EAAA,IAAM,IAAA;AAAA,IACtB,iBAAA,EAAmB,KAAA,CAAM,QAAA,CAAS,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,MAC1C,SAAS,CAAA,CAAE,OAAA;AAAA,MACX,UAAU,CAAA,CAAE;AAAA,KAChB,CAAE;AAAA,GACL,CAAA;AAED,EAAA,OAAO,IAAA;AACX","file":"chunk-E3G7NGCH.js","sourcesContent":["import type { City, RemoteCatalog, Stock, Store } from '@zenky/storefront-api'\n\nexport function getCity(store: Store, cityId?: string | null): City | null {\n if (!store.cities.length) return null\n\n const defaultCity = store.cities.find((c) => c.is_default) ?? store.cities[0] ?? null\n\n if (!cityId) return defaultCity\n\n return store.cities.find((c) => c.id === cityId) ?? defaultCity\n}\n\nexport function getStock(city: City, stockId?: string | null): Stock | null {\n if (!city.stocks?.length) return null\n\n const defaultStock = city.stocks[0] ?? null\n\n if (!stockId) return defaultStock\n\n return city.stocks.find((s) => s.id === stockId) ?? defaultStock\n}\n\nexport function getRemoteCatalog(\n store: Store,\n city: City,\n stock: Stock | null\n): RemoteCatalog | null {\n if (!store.catalogs.length) {\n console.warn('[catalog-resolver] store.catalogs is empty', {\n storeId: store.id,\n cityId: city.id,\n stockId: stock?.id ?? null,\n })\n return null\n }\n\n // Приоритет: точное совпадение city+stock → city-only → глобальный.\n if (stock) {\n const exact = store.catalogs.find((c) => c.city_id === city.id && c.stock_id === stock.id)\n if (exact) return exact\n }\n\n const cityOnly = store.catalogs.find((c) => c.city_id === city.id && c.stock_id === null)\n if (cityOnly) return cityOnly\n\n const global = store.catalogs.find((c) => c.city_id === null && c.stock_id === null)\n if (global) return global\n\n console.warn('[catalog-resolver] no catalog matched (exact/city-only/global)', {\n storeId: store.id,\n cityId: city.id,\n stockId: stock?.id ?? null,\n availableCatalogs: store.catalogs.map((c) => ({\n city_id: c.city_id,\n stock_id: c.stock_id,\n })),\n })\n\n return null\n}\n"]}
|