@wix/himalaya-cli 0.1065.0 → 0.1066.0
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/dist/cli.mjs +173 -45
- package/dist/preview-assets.generated.bin +0 -0
- package/guides/wix-site-to-himi-app.md +2 -2
- package/package.json +2 -2
- package/templates/beauty-salon/dev/index.ts +1 -5
- package/templates/beauty-salon/tier5-src/_shared/himi-layouts.ts +8 -6
- package/templates/beauty-salon/tier5-src/himi-branded-lite-appearance/index.ts +13 -18
- package/templates/beauty-salon/tier5-src/himi-branded-lite-home/index.ts +5 -5
- package/templates/branded-lite/dev/index.ts +2 -6
- package/templates/branded-lite/tier5-src/_shared/himi-layouts.ts +8 -6
- package/templates/branded-lite/tier5-src/himi-branded-lite-appearance/index.ts +13 -18
- package/templates/branded-lite/tier5-src/himi-branded-lite-home/index.ts +5 -5
- package/templates/community-club/dev/index.ts +1 -5
- package/templates/community-club/tier5-src/_shared/himi-layouts.ts +8 -6
- package/templates/community-club/tier5-src/himi-branded-lite-appearance/index.ts +13 -18
- package/templates/community-club/tier5-src/himi-branded-lite-home/index.ts +5 -5
- package/templates/events-meetups/dev/index.ts +1 -5
- package/templates/events-meetups/tier5-src/_shared/himi-layouts.ts +8 -6
- package/templates/events-meetups/tier5-src/himi-branded-lite-appearance/index.ts +13 -18
- package/templates/events-meetups/tier5-src/himi-branded-lite-home/index.ts +5 -5
- package/templates/gym-fitness/dev/index.ts +1 -5
- package/templates/gym-fitness/tier5-src/_shared/himi-layouts.ts +8 -6
- package/templates/gym-fitness/tier5-src/himi-branded-lite-appearance/index.ts +13 -18
- package/templates/gym-fitness/tier5-src/himi-branded-lite-home/index.ts +5 -5
- package/templates/nonprofit-cause/dev/index.ts +1 -5
- package/templates/nonprofit-cause/tier5-src/_shared/himi-layouts.ts +8 -6
- package/templates/nonprofit-cause/tier5-src/himi-branded-lite-appearance/index.ts +13 -18
- package/templates/nonprofit-cause/tier5-src/himi-branded-lite-home/index.ts +5 -5
- package/templates/podcast-creator/dev/index.ts +1 -5
- package/templates/podcast-creator/tier5-src/_shared/himi-layouts.ts +8 -6
- package/templates/podcast-creator/tier5-src/himi-branded-lite-appearance/index.ts +13 -18
- package/templates/podcast-creator/tier5-src/himi-branded-lite-home/index.ts +5 -5
- package/templates/portfolio-creative/dev/index.ts +1 -5
- package/templates/portfolio-creative/tier5-src/_shared/himi-layouts.ts +8 -6
- package/templates/portfolio-creative/tier5-src/himi-branded-lite-appearance/index.ts +13 -18
- package/templates/portfolio-creative/tier5-src/himi-branded-lite-home/index.ts +5 -5
- package/templates/restaurant/dev/index.ts +1 -5
- package/templates/restaurant/tier5-src/_shared/himi-layouts.ts +8 -6
- package/templates/restaurant/tier5-src/himi-branded-lite-appearance/index.ts +13 -18
- package/templates/restaurant/tier5-src/himi-branded-lite-home/index.ts +5 -5
- package/templates/retail-store/dev/index.ts +2 -6
- package/templates/retail-store/tier5-src/_shared/himi-layouts.ts +8 -6
- package/templates/retail-store/tier5-src/himi-branded-lite-appearance/index.ts +13 -18
- package/templates/retail-store/tier5-src/himi-branded-lite-home/index.ts +5 -5
- package/templates/yoga-studio/dev/index.ts +1 -5
- package/templates/yoga-studio/tier5-src/_shared/himi-layouts.ts +8 -6
- package/templates/yoga-studio/tier5-src/himi-branded-lite-appearance/index.ts +13 -18
- package/templates/yoga-studio/tier5-src/himi-branded-lite-home/index.ts +5 -5
|
@@ -19,11 +19,10 @@ import {
|
|
|
19
19
|
interface State {
|
|
20
20
|
/** The pending accent id (persisted on Apply, re-read by the home worker). */
|
|
21
21
|
pendingAccent: string;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
//
|
|
26
|
-
// NOT per-row `$item.` fields, so each static swatch binds its own flat field.
|
|
22
|
+
// Per-accent swatch colors. backgroundColorPath resolves `$service:` paths but NOT
|
|
23
|
+
// per-row `$item.` fields, so each static swatch binds its own flat field.
|
|
24
|
+
// `accentHex_brand` is "" on purpose: the swatch keeps its own accentPrimary token,
|
|
25
|
+
// which is the brand (see accentColor in _shared/himi-layouts.ts).
|
|
27
26
|
accentHex_brand: string;
|
|
28
27
|
accentHex_amber: string;
|
|
29
28
|
accentHex_terracotta: string;
|
|
@@ -54,7 +53,7 @@ function paramValue(arg: unknown, key: string): string {
|
|
|
54
53
|
return typeof result === "string" ? result : "";
|
|
55
54
|
}
|
|
56
55
|
|
|
57
|
-
function build(pendingAccent: string
|
|
56
|
+
function build(pendingAccent: string): State {
|
|
58
57
|
const flags: Record<string, boolean> = {};
|
|
59
58
|
for (const id of ACCENT_IDS) {
|
|
60
59
|
flags[`selected_${id}`] = id === pendingAccent;
|
|
@@ -63,8 +62,7 @@ function build(pendingAccent: string, brandAccent: string): State {
|
|
|
63
62
|
return {
|
|
64
63
|
...flags,
|
|
65
64
|
pendingAccent,
|
|
66
|
-
|
|
67
|
-
accentHex_brand: brandAccent || ACCENT_META.amber.hex,
|
|
65
|
+
accentHex_brand: "",
|
|
68
66
|
accentHex_amber: ACCENT_META.amber.hex,
|
|
69
67
|
accentHex_terracotta: ACCENT_META.terracotta.hex,
|
|
70
68
|
accentHex_sage: ACCENT_META.sage.hex,
|
|
@@ -84,24 +82,21 @@ const svc = defineService<State, {
|
|
|
84
82
|
apply: (state: State) => State;
|
|
85
83
|
reset: (state: State) => State;
|
|
86
84
|
}>("himiBrandedAppearance", {
|
|
87
|
-
state: build(initialAccent()
|
|
85
|
+
state: build(initialAccent()),
|
|
88
86
|
actions: {
|
|
89
|
-
// onAppear: re-read the persisted accent
|
|
90
|
-
//
|
|
91
|
-
sync: (
|
|
92
|
-
const brandAccent = paramValue(arg, "brandAccent") || state.brandAccent;
|
|
93
|
-
return build(initialAccent(), brandAccent);
|
|
94
|
-
},
|
|
87
|
+
// onAppear: re-read the persisted accent so the swatches reflect reality. An older
|
|
88
|
+
// descriptor may still pass a `brandAccent`; it is not used (the Brand swatch is the token).
|
|
89
|
+
sync: () => build(initialAccent()),
|
|
95
90
|
// Tapping an accent swatch marks it pending (persisted on Apply).
|
|
96
91
|
selectAccent: (state, arg) => {
|
|
97
92
|
const id = paramValue(arg, "id");
|
|
98
93
|
if (!isAccentId(id)) return state;
|
|
99
|
-
return build(id
|
|
94
|
+
return build(id);
|
|
100
95
|
},
|
|
101
96
|
// Apply: persist the accent; the home worker re-reads it on launch.
|
|
102
97
|
apply: (state) => {
|
|
103
98
|
try { storage()?.setItem(ACCENT_KEY, state.pendingAccent); } catch { /* best-effort */ }
|
|
104
|
-
return build(state.pendingAccent
|
|
99
|
+
return build(state.pendingAccent);
|
|
105
100
|
},
|
|
106
101
|
// Reset: clear the override, reverting to the brand accent.
|
|
107
102
|
reset: (state) => {
|
|
@@ -110,7 +105,7 @@ const svc = defineService<State, {
|
|
|
110
105
|
if (store?.removeItem) store.removeItem(ACCENT_KEY);
|
|
111
106
|
else store?.setItem(ACCENT_KEY, "");
|
|
112
107
|
} catch { /* best-effort */ }
|
|
113
|
-
return build(DEFAULT_ACCENT
|
|
108
|
+
return build(DEFAULT_ACCENT);
|
|
114
109
|
},
|
|
115
110
|
},
|
|
116
111
|
});
|
|
@@ -338,11 +338,11 @@ function storedLayout(): string | null {
|
|
|
338
338
|
function storedAccent(): string {
|
|
339
339
|
try { return storage()?.getItem(ACCENT_KEY) ?? ""; } catch { return ""; }
|
|
340
340
|
}
|
|
341
|
-
//
|
|
342
|
-
//
|
|
343
|
-
//
|
|
344
|
-
function resolveAccent(
|
|
345
|
-
return resolveAccentColor(storedAccent()
|
|
341
|
+
// The member's chosen accent (storage), else "" — the surface keeps its accentPrimary token,
|
|
342
|
+
// which is the brand. An older descriptor's `brandAccent` param is ignored: it was a copy of
|
|
343
|
+
// the brand that a hand edit of tokens.json left behind.
|
|
344
|
+
function resolveAccent(_arg?: unknown): string {
|
|
345
|
+
return resolveAccentColor(storedAccent());
|
|
346
346
|
}
|
|
347
347
|
|
|
348
348
|
// onAppear param reader (the himi-branded-lite-cms pattern): the descriptor
|
|
@@ -1958,7 +1958,6 @@ const SCREENS = runtimeSetting({
|
|
|
1958
1958
|
"verticals": "[\"feed\",\"events\",\"blog\",\"groups\",\"cms\"]",
|
|
1959
1959
|
"homeModules": "[{\"id\":\"saved\",\"label\":\"Saved on this device\",\"dataSource\":\"device.saved_items\",\"emptyWhen\":[\"noSavedContent\"]},{\"id\":\"section_0\",\"label\":\"Discover 1\",\"dataSource\":\"communityPulse.section0\",\"emptyWhen\":[\"noMemberAvatars\"]},{\"id\":\"section_1\",\"label\":\"Announcement\",\"dataSource\":\"communityPulse.section1\",\"emptyWhen\":[\"noAnnouncement\",\"noUpcomingEvents\"]},{\"id\":\"section_2\",\"label\":\"Groups\",\"dataSource\":\"communityPulse.section2\",\"emptyWhen\":[\"noGroupCards\"]},{\"id\":\"section_3\",\"label\":\"Latest activity\",\"dataSource\":\"communityPulse.section3\"}]",
|
|
1960
1960
|
"ownerDefaultLayout": "communityPulse",
|
|
1961
|
-
"brandAccent": "#6C3FC4",
|
|
1962
1961
|
"copy": "{\"home.activityTitle\":\"Latest activity\",\"home.announcementCaption\":\"Announcement\",\"home.eventsTitle\":\"Upcoming events\",\"home.groupsSubtitle\":\"Find your people.\",\"home.groupsTitle\":\"Groups\",\"home.membersCaption\":\"Our members\",\"home.onboardingBody\":\"Join groups, RSVP to events, and keep up with the community feed — all in one place.\"}"
|
|
1963
1962
|
}
|
|
1964
1963
|
}
|
|
@@ -4223,10 +4222,7 @@ const SCREENS = runtimeSetting({
|
|
|
4223
4222
|
"bottom": 28
|
|
4224
4223
|
},
|
|
4225
4224
|
"onAppear": {
|
|
4226
|
-
"actionId": "tier5.himiBrandedAppearance.sync"
|
|
4227
|
-
"params": {
|
|
4228
|
-
"brandAccent": "#6C3FC4"
|
|
4229
|
-
}
|
|
4225
|
+
"actionId": "tier5.himiBrandedAppearance.sync"
|
|
4230
4226
|
}
|
|
4231
4227
|
}
|
|
4232
4228
|
},
|
|
@@ -134,12 +134,14 @@ export function isAccentId(x: unknown): x is AccentId {
|
|
|
134
134
|
return typeof x === "string" && (ACCENT_IDS as readonly string[]).includes(x);
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
-
/** Resolve an accent id to
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
137
|
+
/** Resolve an accent id to its curated hex, or "" for `brand` and any unknown value.
|
|
138
|
+
* "" is deliberate: a bound `backgroundColorPath` that resolves empty keeps the surface's
|
|
139
|
+
* own `accentPrimary` token on every renderer, and that token IS the brand — after a
|
|
140
|
+
* `site analyze --apply` and after a hand edit of tokens.json alike. A brand colour copied
|
|
141
|
+
* into the descriptor instead (the old `brandAccent` param) went stale on the second path:
|
|
142
|
+
* the Home pill kept the template's blue after a rebrand. */
|
|
143
|
+
export function accentColor(id: string): string {
|
|
144
|
+
return isAccentId(id) ? ACCENT_META[id].hex : "";
|
|
143
145
|
}
|
|
144
146
|
|
|
145
147
|
/** Content-derived default: booking intent > deep catalog > editorial (blog-forward) > balanced.
|
|
@@ -19,11 +19,10 @@ import {
|
|
|
19
19
|
interface State {
|
|
20
20
|
/** The pending accent id (persisted on Apply, re-read by the home worker). */
|
|
21
21
|
pendingAccent: string;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
//
|
|
26
|
-
// NOT per-row `$item.` fields, so each static swatch binds its own flat field.
|
|
22
|
+
// Per-accent swatch colors. backgroundColorPath resolves `$service:` paths but NOT
|
|
23
|
+
// per-row `$item.` fields, so each static swatch binds its own flat field.
|
|
24
|
+
// `accentHex_brand` is "" on purpose: the swatch keeps its own accentPrimary token,
|
|
25
|
+
// which is the brand (see accentColor in _shared/himi-layouts.ts).
|
|
27
26
|
accentHex_brand: string;
|
|
28
27
|
accentHex_amber: string;
|
|
29
28
|
accentHex_terracotta: string;
|
|
@@ -54,7 +53,7 @@ function paramValue(arg: unknown, key: string): string {
|
|
|
54
53
|
return typeof result === "string" ? result : "";
|
|
55
54
|
}
|
|
56
55
|
|
|
57
|
-
function build(pendingAccent: string
|
|
56
|
+
function build(pendingAccent: string): State {
|
|
58
57
|
const flags: Record<string, boolean> = {};
|
|
59
58
|
for (const id of ACCENT_IDS) {
|
|
60
59
|
flags[`selected_${id}`] = id === pendingAccent;
|
|
@@ -63,8 +62,7 @@ function build(pendingAccent: string, brandAccent: string): State {
|
|
|
63
62
|
return {
|
|
64
63
|
...flags,
|
|
65
64
|
pendingAccent,
|
|
66
|
-
|
|
67
|
-
accentHex_brand: brandAccent || ACCENT_META.amber.hex,
|
|
65
|
+
accentHex_brand: "",
|
|
68
66
|
accentHex_amber: ACCENT_META.amber.hex,
|
|
69
67
|
accentHex_terracotta: ACCENT_META.terracotta.hex,
|
|
70
68
|
accentHex_sage: ACCENT_META.sage.hex,
|
|
@@ -84,24 +82,21 @@ const svc = defineService<State, {
|
|
|
84
82
|
apply: (state: State) => State;
|
|
85
83
|
reset: (state: State) => State;
|
|
86
84
|
}>("himiBrandedAppearance", {
|
|
87
|
-
state: build(initialAccent()
|
|
85
|
+
state: build(initialAccent()),
|
|
88
86
|
actions: {
|
|
89
|
-
// onAppear: re-read the persisted accent
|
|
90
|
-
//
|
|
91
|
-
sync: (
|
|
92
|
-
const brandAccent = paramValue(arg, "brandAccent") || state.brandAccent;
|
|
93
|
-
return build(initialAccent(), brandAccent);
|
|
94
|
-
},
|
|
87
|
+
// onAppear: re-read the persisted accent so the swatches reflect reality. An older
|
|
88
|
+
// descriptor may still pass a `brandAccent`; it is not used (the Brand swatch is the token).
|
|
89
|
+
sync: () => build(initialAccent()),
|
|
95
90
|
// Tapping an accent swatch marks it pending (persisted on Apply).
|
|
96
91
|
selectAccent: (state, arg) => {
|
|
97
92
|
const id = paramValue(arg, "id");
|
|
98
93
|
if (!isAccentId(id)) return state;
|
|
99
|
-
return build(id
|
|
94
|
+
return build(id);
|
|
100
95
|
},
|
|
101
96
|
// Apply: persist the accent; the home worker re-reads it on launch.
|
|
102
97
|
apply: (state) => {
|
|
103
98
|
try { storage()?.setItem(ACCENT_KEY, state.pendingAccent); } catch { /* best-effort */ }
|
|
104
|
-
return build(state.pendingAccent
|
|
99
|
+
return build(state.pendingAccent);
|
|
105
100
|
},
|
|
106
101
|
// Reset: clear the override, reverting to the brand accent.
|
|
107
102
|
reset: (state) => {
|
|
@@ -110,7 +105,7 @@ const svc = defineService<State, {
|
|
|
110
105
|
if (store?.removeItem) store.removeItem(ACCENT_KEY);
|
|
111
106
|
else store?.setItem(ACCENT_KEY, "");
|
|
112
107
|
} catch { /* best-effort */ }
|
|
113
|
-
return build(DEFAULT_ACCENT
|
|
108
|
+
return build(DEFAULT_ACCENT);
|
|
114
109
|
},
|
|
115
110
|
},
|
|
116
111
|
});
|
|
@@ -338,11 +338,11 @@ function storedLayout(): string | null {
|
|
|
338
338
|
function storedAccent(): string {
|
|
339
339
|
try { return storage()?.getItem(ACCENT_KEY) ?? ""; } catch { return ""; }
|
|
340
340
|
}
|
|
341
|
-
//
|
|
342
|
-
//
|
|
343
|
-
//
|
|
344
|
-
function resolveAccent(
|
|
345
|
-
return resolveAccentColor(storedAccent()
|
|
341
|
+
// The member's chosen accent (storage), else "" — the surface keeps its accentPrimary token,
|
|
342
|
+
// which is the brand. An older descriptor's `brandAccent` param is ignored: it was a copy of
|
|
343
|
+
// the brand that a hand edit of tokens.json left behind.
|
|
344
|
+
function resolveAccent(_arg?: unknown): string {
|
|
345
|
+
return resolveAccentColor(storedAccent());
|
|
346
346
|
}
|
|
347
347
|
|
|
348
348
|
// onAppear param reader (the himi-branded-lite-cms pattern): the descriptor
|
|
@@ -2142,7 +2142,6 @@ const SCREENS = runtimeSetting({
|
|
|
2142
2142
|
"verticals": "[\"feed\",\"events\",\"blog\",\"groups\"]",
|
|
2143
2143
|
"homeModules": "[{\"id\":\"saved\",\"label\":\"Saved on this device\",\"dataSource\":\"device.saved_items\",\"emptyWhen\":[\"noSavedContent\"]},{\"id\":\"section_0\",\"label\":\"Next up\",\"dataSource\":\"eventsFirst.section0\",\"emptyWhen\":[\"noNextEvent\"]},{\"id\":\"section_1\",\"label\":\"This season\",\"dataSource\":\"eventsFirst.section1\",\"emptyWhen\":[\"noUpcomingEvents\"]},{\"id\":\"section_2\",\"label\":\"Discover 3\",\"dataSource\":\"eventsFirst.section2\"},{\"id\":\"section_3\",\"label\":\"Latest from the community\",\"dataSource\":\"eventsFirst.section3\"}]",
|
|
2144
2144
|
"ownerDefaultLayout": "eventsFirst",
|
|
2145
|
-
"brandAccent": "#5B3E96",
|
|
2146
2145
|
"copy": "{\"home.activityTitle\":\"Latest from the community\",\"home.agendaTitle\":\"This season\",\"home.allEventsCta\":\"All events\",\"home.eventsTitle\":\"Upcoming events\",\"home.groupsSubtitle\":\"Find your crew.\",\"home.groupsTitle\":\"Groups\",\"home.membersCaption\":\"Who's coming\",\"home.nextUpCaption\":\"Next up\",\"home.onboardingBody\":\"See what's next, RSVP in a couple of taps, and keep up with the community between events — all in one place.\",\"home.recapsCaption\":\"Event recaps\",\"home.rsvpCta\":\"View event & RSVP\"}"
|
|
2147
2146
|
}
|
|
2148
2147
|
}
|
|
@@ -4407,10 +4406,7 @@ const SCREENS = runtimeSetting({
|
|
|
4407
4406
|
"bottom": 28
|
|
4408
4407
|
},
|
|
4409
4408
|
"onAppear": {
|
|
4410
|
-
"actionId": "tier5.himiBrandedAppearance.sync"
|
|
4411
|
-
"params": {
|
|
4412
|
-
"brandAccent": "#5B3E96"
|
|
4413
|
-
}
|
|
4409
|
+
"actionId": "tier5.himiBrandedAppearance.sync"
|
|
4414
4410
|
}
|
|
4415
4411
|
}
|
|
4416
4412
|
},
|
|
@@ -134,12 +134,14 @@ export function isAccentId(x: unknown): x is AccentId {
|
|
|
134
134
|
return typeof x === "string" && (ACCENT_IDS as readonly string[]).includes(x);
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
-
/** Resolve an accent id to
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
137
|
+
/** Resolve an accent id to its curated hex, or "" for `brand` and any unknown value.
|
|
138
|
+
* "" is deliberate: a bound `backgroundColorPath` that resolves empty keeps the surface's
|
|
139
|
+
* own `accentPrimary` token on every renderer, and that token IS the brand — after a
|
|
140
|
+
* `site analyze --apply` and after a hand edit of tokens.json alike. A brand colour copied
|
|
141
|
+
* into the descriptor instead (the old `brandAccent` param) went stale on the second path:
|
|
142
|
+
* the Home pill kept the template's blue after a rebrand. */
|
|
143
|
+
export function accentColor(id: string): string {
|
|
144
|
+
return isAccentId(id) ? ACCENT_META[id].hex : "";
|
|
143
145
|
}
|
|
144
146
|
|
|
145
147
|
/** Content-derived default: booking intent > deep catalog > editorial (blog-forward) > balanced.
|
|
@@ -19,11 +19,10 @@ import {
|
|
|
19
19
|
interface State {
|
|
20
20
|
/** The pending accent id (persisted on Apply, re-read by the home worker). */
|
|
21
21
|
pendingAccent: string;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
//
|
|
26
|
-
// NOT per-row `$item.` fields, so each static swatch binds its own flat field.
|
|
22
|
+
// Per-accent swatch colors. backgroundColorPath resolves `$service:` paths but NOT
|
|
23
|
+
// per-row `$item.` fields, so each static swatch binds its own flat field.
|
|
24
|
+
// `accentHex_brand` is "" on purpose: the swatch keeps its own accentPrimary token,
|
|
25
|
+
// which is the brand (see accentColor in _shared/himi-layouts.ts).
|
|
27
26
|
accentHex_brand: string;
|
|
28
27
|
accentHex_amber: string;
|
|
29
28
|
accentHex_terracotta: string;
|
|
@@ -54,7 +53,7 @@ function paramValue(arg: unknown, key: string): string {
|
|
|
54
53
|
return typeof result === "string" ? result : "";
|
|
55
54
|
}
|
|
56
55
|
|
|
57
|
-
function build(pendingAccent: string
|
|
56
|
+
function build(pendingAccent: string): State {
|
|
58
57
|
const flags: Record<string, boolean> = {};
|
|
59
58
|
for (const id of ACCENT_IDS) {
|
|
60
59
|
flags[`selected_${id}`] = id === pendingAccent;
|
|
@@ -63,8 +62,7 @@ function build(pendingAccent: string, brandAccent: string): State {
|
|
|
63
62
|
return {
|
|
64
63
|
...flags,
|
|
65
64
|
pendingAccent,
|
|
66
|
-
|
|
67
|
-
accentHex_brand: brandAccent || ACCENT_META.amber.hex,
|
|
65
|
+
accentHex_brand: "",
|
|
68
66
|
accentHex_amber: ACCENT_META.amber.hex,
|
|
69
67
|
accentHex_terracotta: ACCENT_META.terracotta.hex,
|
|
70
68
|
accentHex_sage: ACCENT_META.sage.hex,
|
|
@@ -84,24 +82,21 @@ const svc = defineService<State, {
|
|
|
84
82
|
apply: (state: State) => State;
|
|
85
83
|
reset: (state: State) => State;
|
|
86
84
|
}>("himiBrandedAppearance", {
|
|
87
|
-
state: build(initialAccent()
|
|
85
|
+
state: build(initialAccent()),
|
|
88
86
|
actions: {
|
|
89
|
-
// onAppear: re-read the persisted accent
|
|
90
|
-
//
|
|
91
|
-
sync: (
|
|
92
|
-
const brandAccent = paramValue(arg, "brandAccent") || state.brandAccent;
|
|
93
|
-
return build(initialAccent(), brandAccent);
|
|
94
|
-
},
|
|
87
|
+
// onAppear: re-read the persisted accent so the swatches reflect reality. An older
|
|
88
|
+
// descriptor may still pass a `brandAccent`; it is not used (the Brand swatch is the token).
|
|
89
|
+
sync: () => build(initialAccent()),
|
|
95
90
|
// Tapping an accent swatch marks it pending (persisted on Apply).
|
|
96
91
|
selectAccent: (state, arg) => {
|
|
97
92
|
const id = paramValue(arg, "id");
|
|
98
93
|
if (!isAccentId(id)) return state;
|
|
99
|
-
return build(id
|
|
94
|
+
return build(id);
|
|
100
95
|
},
|
|
101
96
|
// Apply: persist the accent; the home worker re-reads it on launch.
|
|
102
97
|
apply: (state) => {
|
|
103
98
|
try { storage()?.setItem(ACCENT_KEY, state.pendingAccent); } catch { /* best-effort */ }
|
|
104
|
-
return build(state.pendingAccent
|
|
99
|
+
return build(state.pendingAccent);
|
|
105
100
|
},
|
|
106
101
|
// Reset: clear the override, reverting to the brand accent.
|
|
107
102
|
reset: (state) => {
|
|
@@ -110,7 +105,7 @@ const svc = defineService<State, {
|
|
|
110
105
|
if (store?.removeItem) store.removeItem(ACCENT_KEY);
|
|
111
106
|
else store?.setItem(ACCENT_KEY, "");
|
|
112
107
|
} catch { /* best-effort */ }
|
|
113
|
-
return build(DEFAULT_ACCENT
|
|
108
|
+
return build(DEFAULT_ACCENT);
|
|
114
109
|
},
|
|
115
110
|
},
|
|
116
111
|
});
|
|
@@ -338,11 +338,11 @@ function storedLayout(): string | null {
|
|
|
338
338
|
function storedAccent(): string {
|
|
339
339
|
try { return storage()?.getItem(ACCENT_KEY) ?? ""; } catch { return ""; }
|
|
340
340
|
}
|
|
341
|
-
//
|
|
342
|
-
//
|
|
343
|
-
//
|
|
344
|
-
function resolveAccent(
|
|
345
|
-
return resolveAccentColor(storedAccent()
|
|
341
|
+
// The member's chosen accent (storage), else "" — the surface keeps its accentPrimary token,
|
|
342
|
+
// which is the brand. An older descriptor's `brandAccent` param is ignored: it was a copy of
|
|
343
|
+
// the brand that a hand edit of tokens.json left behind.
|
|
344
|
+
function resolveAccent(_arg?: unknown): string {
|
|
345
|
+
return resolveAccentColor(storedAccent());
|
|
346
346
|
}
|
|
347
347
|
|
|
348
348
|
// onAppear param reader (the himi-branded-lite-cms pattern): the descriptor
|
|
@@ -2423,7 +2423,6 @@ const SCREENS = runtimeSetting({
|
|
|
2423
2423
|
"verticals": "[\"store\",\"bookings\",\"plans\",\"events\",\"blog\"]",
|
|
2424
2424
|
"homeModules": "[{\"id\":\"member_progress\",\"label\":\"This week's schedule\",\"dataSource\":\"member.bookings.schedule\",\"emptyWhen\":[\"hideMemberProgress\"]},{\"id\":\"up_next\",\"label\":\"Up next\",\"dataSource\":\"member.bookings\",\"emptyWhen\":[\"hideNextBooking\",\"hidePersonalError\"]},{\"id\":\"saved\",\"label\":\"Saved on this device\",\"dataSource\":\"device.saved_items\",\"emptyWhen\":[\"noSavedContent\"]},{\"id\":\"section_0\",\"label\":\"Discover 1\",\"dataSource\":\"trainingFirst.section0\",\"emptyWhen\":[\"hideHeroImage\"]},{\"id\":\"section_1\",\"label\":\"__HIMI_APP_NAME__\",\"dataSource\":\"trainingFirst.section1\"}]",
|
|
2425
2425
|
"ownerDefaultLayout": "trainingFirst",
|
|
2426
|
-
"brandAccent": "#C1552F",
|
|
2427
2426
|
"copy": "{\"home.storeFeaturedTitle\":\"Shop the gear\"}"
|
|
2428
2427
|
}
|
|
2429
2428
|
}
|
|
@@ -5129,10 +5128,7 @@ const SCREENS = runtimeSetting({
|
|
|
5129
5128
|
"bottom": 28
|
|
5130
5129
|
},
|
|
5131
5130
|
"onAppear": {
|
|
5132
|
-
"actionId": "tier5.himiBrandedAppearance.sync"
|
|
5133
|
-
"params": {
|
|
5134
|
-
"brandAccent": "#C1552F"
|
|
5135
|
-
}
|
|
5131
|
+
"actionId": "tier5.himiBrandedAppearance.sync"
|
|
5136
5132
|
}
|
|
5137
5133
|
}
|
|
5138
5134
|
},
|
|
@@ -134,12 +134,14 @@ export function isAccentId(x: unknown): x is AccentId {
|
|
|
134
134
|
return typeof x === "string" && (ACCENT_IDS as readonly string[]).includes(x);
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
-
/** Resolve an accent id to
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
137
|
+
/** Resolve an accent id to its curated hex, or "" for `brand` and any unknown value.
|
|
138
|
+
* "" is deliberate: a bound `backgroundColorPath` that resolves empty keeps the surface's
|
|
139
|
+
* own `accentPrimary` token on every renderer, and that token IS the brand — after a
|
|
140
|
+
* `site analyze --apply` and after a hand edit of tokens.json alike. A brand colour copied
|
|
141
|
+
* into the descriptor instead (the old `brandAccent` param) went stale on the second path:
|
|
142
|
+
* the Home pill kept the template's blue after a rebrand. */
|
|
143
|
+
export function accentColor(id: string): string {
|
|
144
|
+
return isAccentId(id) ? ACCENT_META[id].hex : "";
|
|
143
145
|
}
|
|
144
146
|
|
|
145
147
|
/** Content-derived default: booking intent > deep catalog > editorial (blog-forward) > balanced.
|
|
@@ -19,11 +19,10 @@ import {
|
|
|
19
19
|
interface State {
|
|
20
20
|
/** The pending accent id (persisted on Apply, re-read by the home worker). */
|
|
21
21
|
pendingAccent: string;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
//
|
|
26
|
-
// NOT per-row `$item.` fields, so each static swatch binds its own flat field.
|
|
22
|
+
// Per-accent swatch colors. backgroundColorPath resolves `$service:` paths but NOT
|
|
23
|
+
// per-row `$item.` fields, so each static swatch binds its own flat field.
|
|
24
|
+
// `accentHex_brand` is "" on purpose: the swatch keeps its own accentPrimary token,
|
|
25
|
+
// which is the brand (see accentColor in _shared/himi-layouts.ts).
|
|
27
26
|
accentHex_brand: string;
|
|
28
27
|
accentHex_amber: string;
|
|
29
28
|
accentHex_terracotta: string;
|
|
@@ -54,7 +53,7 @@ function paramValue(arg: unknown, key: string): string {
|
|
|
54
53
|
return typeof result === "string" ? result : "";
|
|
55
54
|
}
|
|
56
55
|
|
|
57
|
-
function build(pendingAccent: string
|
|
56
|
+
function build(pendingAccent: string): State {
|
|
58
57
|
const flags: Record<string, boolean> = {};
|
|
59
58
|
for (const id of ACCENT_IDS) {
|
|
60
59
|
flags[`selected_${id}`] = id === pendingAccent;
|
|
@@ -63,8 +62,7 @@ function build(pendingAccent: string, brandAccent: string): State {
|
|
|
63
62
|
return {
|
|
64
63
|
...flags,
|
|
65
64
|
pendingAccent,
|
|
66
|
-
|
|
67
|
-
accentHex_brand: brandAccent || ACCENT_META.amber.hex,
|
|
65
|
+
accentHex_brand: "",
|
|
68
66
|
accentHex_amber: ACCENT_META.amber.hex,
|
|
69
67
|
accentHex_terracotta: ACCENT_META.terracotta.hex,
|
|
70
68
|
accentHex_sage: ACCENT_META.sage.hex,
|
|
@@ -84,24 +82,21 @@ const svc = defineService<State, {
|
|
|
84
82
|
apply: (state: State) => State;
|
|
85
83
|
reset: (state: State) => State;
|
|
86
84
|
}>("himiBrandedAppearance", {
|
|
87
|
-
state: build(initialAccent()
|
|
85
|
+
state: build(initialAccent()),
|
|
88
86
|
actions: {
|
|
89
|
-
// onAppear: re-read the persisted accent
|
|
90
|
-
//
|
|
91
|
-
sync: (
|
|
92
|
-
const brandAccent = paramValue(arg, "brandAccent") || state.brandAccent;
|
|
93
|
-
return build(initialAccent(), brandAccent);
|
|
94
|
-
},
|
|
87
|
+
// onAppear: re-read the persisted accent so the swatches reflect reality. An older
|
|
88
|
+
// descriptor may still pass a `brandAccent`; it is not used (the Brand swatch is the token).
|
|
89
|
+
sync: () => build(initialAccent()),
|
|
95
90
|
// Tapping an accent swatch marks it pending (persisted on Apply).
|
|
96
91
|
selectAccent: (state, arg) => {
|
|
97
92
|
const id = paramValue(arg, "id");
|
|
98
93
|
if (!isAccentId(id)) return state;
|
|
99
|
-
return build(id
|
|
94
|
+
return build(id);
|
|
100
95
|
},
|
|
101
96
|
// Apply: persist the accent; the home worker re-reads it on launch.
|
|
102
97
|
apply: (state) => {
|
|
103
98
|
try { storage()?.setItem(ACCENT_KEY, state.pendingAccent); } catch { /* best-effort */ }
|
|
104
|
-
return build(state.pendingAccent
|
|
99
|
+
return build(state.pendingAccent);
|
|
105
100
|
},
|
|
106
101
|
// Reset: clear the override, reverting to the brand accent.
|
|
107
102
|
reset: (state) => {
|
|
@@ -110,7 +105,7 @@ const svc = defineService<State, {
|
|
|
110
105
|
if (store?.removeItem) store.removeItem(ACCENT_KEY);
|
|
111
106
|
else store?.setItem(ACCENT_KEY, "");
|
|
112
107
|
} catch { /* best-effort */ }
|
|
113
|
-
return build(DEFAULT_ACCENT
|
|
108
|
+
return build(DEFAULT_ACCENT);
|
|
114
109
|
},
|
|
115
110
|
},
|
|
116
111
|
});
|
|
@@ -338,11 +338,11 @@ function storedLayout(): string | null {
|
|
|
338
338
|
function storedAccent(): string {
|
|
339
339
|
try { return storage()?.getItem(ACCENT_KEY) ?? ""; } catch { return ""; }
|
|
340
340
|
}
|
|
341
|
-
//
|
|
342
|
-
//
|
|
343
|
-
//
|
|
344
|
-
function resolveAccent(
|
|
345
|
-
return resolveAccentColor(storedAccent()
|
|
341
|
+
// The member's chosen accent (storage), else "" — the surface keeps its accentPrimary token,
|
|
342
|
+
// which is the brand. An older descriptor's `brandAccent` param is ignored: it was a copy of
|
|
343
|
+
// the brand that a hand edit of tokens.json left behind.
|
|
344
|
+
function resolveAccent(_arg?: unknown): string {
|
|
345
|
+
return resolveAccentColor(storedAccent());
|
|
346
346
|
}
|
|
347
347
|
|
|
348
348
|
// onAppear param reader (the himi-branded-lite-cms pattern): the descriptor
|
|
@@ -2078,7 +2078,6 @@ const SCREENS = runtimeSetting({
|
|
|
2078
2078
|
"verticals": "[\"plans\",\"feed\",\"events\",\"blog\",\"groups\"]",
|
|
2079
2079
|
"homeModules": "[{\"id\":\"saved\",\"label\":\"Saved on this device\",\"dataSource\":\"device.saved_items\",\"emptyWhen\":[\"noSavedContent\"]},{\"id\":\"section_0\",\"label\":\"Discover 1\",\"dataSource\":\"communityPulse.section0\",\"emptyWhen\":[\"noMemberAvatars\"]},{\"id\":\"section_1\",\"label\":\"From the field\",\"dataSource\":\"communityPulse.section1\",\"emptyWhen\":[\"noAnnouncement\",\"noUpcomingEvents\"]},{\"id\":\"section_2\",\"label\":\"Chapters & teams\",\"dataSource\":\"communityPulse.section2\",\"emptyWhen\":[\"noGroupCards\"]},{\"id\":\"section_3\",\"label\":\"Latest from the community\",\"dataSource\":\"communityPulse.section3\"}]",
|
|
2080
2080
|
"ownerDefaultLayout": "communityPulse",
|
|
2081
|
-
"brandAccent": "#0F6B5C",
|
|
2082
2081
|
"copy": "{\"home.activityTitle\":\"Latest from the community\",\"home.announcementCaption\":\"From the field\",\"home.eventsTitle\":\"Volunteer opportunities\",\"home.groupsSubtitle\":\"Find your cause and pitch in.\",\"home.groupsTitle\":\"Chapters & teams\",\"home.joinConversationCta\":\"Share your story\",\"home.membersCaption\":\"Our volunteers\",\"home.onboardingBody\":\"Find a way to give, sign up to volunteer, and follow the mission's impact — all in one place.\"}"
|
|
2083
2082
|
}
|
|
2084
2083
|
}
|
|
@@ -4520,10 +4519,7 @@ const SCREENS = runtimeSetting({
|
|
|
4520
4519
|
"bottom": 28
|
|
4521
4520
|
},
|
|
4522
4521
|
"onAppear": {
|
|
4523
|
-
"actionId": "tier5.himiBrandedAppearance.sync"
|
|
4524
|
-
"params": {
|
|
4525
|
-
"brandAccent": "#0F6B5C"
|
|
4526
|
-
}
|
|
4522
|
+
"actionId": "tier5.himiBrandedAppearance.sync"
|
|
4527
4523
|
}
|
|
4528
4524
|
}
|
|
4529
4525
|
},
|
|
@@ -134,12 +134,14 @@ export function isAccentId(x: unknown): x is AccentId {
|
|
|
134
134
|
return typeof x === "string" && (ACCENT_IDS as readonly string[]).includes(x);
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
-
/** Resolve an accent id to
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
137
|
+
/** Resolve an accent id to its curated hex, or "" for `brand` and any unknown value.
|
|
138
|
+
* "" is deliberate: a bound `backgroundColorPath` that resolves empty keeps the surface's
|
|
139
|
+
* own `accentPrimary` token on every renderer, and that token IS the brand — after a
|
|
140
|
+
* `site analyze --apply` and after a hand edit of tokens.json alike. A brand colour copied
|
|
141
|
+
* into the descriptor instead (the old `brandAccent` param) went stale on the second path:
|
|
142
|
+
* the Home pill kept the template's blue after a rebrand. */
|
|
143
|
+
export function accentColor(id: string): string {
|
|
144
|
+
return isAccentId(id) ? ACCENT_META[id].hex : "";
|
|
143
145
|
}
|
|
144
146
|
|
|
145
147
|
/** Content-derived default: booking intent > deep catalog > editorial (blog-forward) > balanced.
|