@valbuild/shared 0.150.1 → 0.150.3

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 CHANGED
@@ -1,5 +1,36 @@
1
1
  # @valbuild/shared
2
2
 
3
+ ## 0.150.3
4
+
5
+ ### Patch Changes
6
+
7
+ - [#954](https://github.com/valbuild/val/pull/954) [`bc0cc43`](https://github.com/valbuild/val/commit/bc0cc433e157cca08f9ee384a4fb8be9bd3dad2c) Thanks [@freekh](https://github.com/freekh)! - Proposals in the Studio, reworked:
8
+
9
+ - **Save becomes Publish.** In a proposal, one split button stands where Publish is on the site. Its main half is the next step (Save, then Build, then Publish), and its caret offers every step, so you can publish straight away: Publish saves first. The separate Publish button beside the switcher is gone.
10
+ - **The switcher is where the proposal is managed**, as on a phone: its name and changes, Compare with the site, Rename, Copy link and Close, then where else to go.
11
+ - **Upgrade proposals** have one Publish (the bar's), say what they upgrade in the Publish dialog, cannot be published while Val Build is still working them out, are discarded rather than closed, and have their own icon.
12
+ - **A published proposal** shows a dialog with the ways out (the site, a new proposal, all proposals), since nothing more can be done in it.
13
+ - **Notices about where you are** (an upgrade, an upgrade under way, a restore) pop up from the bottom right and stay until dismissed; a dismissed one folds into the status bar and comes back from there.
14
+ - **No more flash of the site's chrome** at a proposal's address: the bar says "Loading…" until it knows, a return visit starts in the proposal at once, and opening a proposal says "Opening …" while the browser gets there.
15
+ - **After a save**, "Updating the preview…" and a failed render check are shown beside the switcher, and the status bar counts what is not saved to the proposal instead of saying "All changes saved".
16
+ - **Dialogs** dim the Studio instead of hiding it.
17
+ - **`theme.proposal`** in `s.settings()` sets the colour the Studio wears in a proposal (Val's violet when unset), under Settings → Studio. Like the accent, its shades are generated so text on them stays legible.
18
+
19
+ - Updated dependencies [[`bc0cc43`](https://github.com/valbuild/val/commit/bc0cc433e157cca08f9ee384a4fb8be9bd3dad2c)]:
20
+ - @valbuild/core@0.150.3
21
+
22
+ ## 0.150.2
23
+
24
+ ### Patch Changes
25
+
26
+ - [#949](https://github.com/valbuild/val/pull/949) [`36412b2`](https://github.com/valbuild/val/commit/36412b28bb009083f652b26462b76a74c80ff595) Thanks [@freekh](https://github.com/freekh)! - Val Studio now shows content analytics beside the content being edited, for a hosted project with content analytics switched on. Each field and list row shows how many page views it was seen in (hover for how many it was on the page in, and the share). The heading of what is open says the same for all of it, and lists what in it was seen most, by the names the Studio gives them everywhere else. Nothing is shown, and nothing is asked of Val Build, for a project with analytics off or a Studio not signed in to Val Build.
27
+
28
+ - [#953](https://github.com/valbuild/val/pull/953) [`8f598b6`](https://github.com/valbuild/val/commit/8f598b618b794e59ef5b9c6ef94650be4ff006e7) Thanks [@freekh](https://github.com/freekh)! - A proposal's typecheck no longer downloads TypeScript again for its second check. The compiler (about 13 MB) is kept by the typecheck's worker once fetched, for every check that asks for the same version after it.
29
+
30
+ - [#952](https://github.com/valbuild/val/pull/952) [`95d17e6`](https://github.com/valbuild/val/commit/95d17e6bbecceb2f09d6a6226808e9c60b2d4795) Thanks [@freekh](https://github.com/freekh)! - A proposal's typecheck (an upgrade, or a proposal with dependencies of its own) now checks the proposal first, and checks the site as it is only when the proposal has type errors, to tell the errors the site already had from the ones the proposal adds. A proposal that typechecks cleanly is done in one check instead of two, which is most of them. A site with no lockfile on record no longer has one worked out for it unless the second check needs it.
31
+ - Updated dependencies [[`155a079`](https://github.com/valbuild/val/commit/155a0792c2a437a1cbcdd6342131999be70e0d70)]:
32
+ - @valbuild/core@0.150.2
33
+
3
34
  ## 0.150.1
4
35
 
5
36
  ### Patch Changes
@@ -2348,6 +2348,9 @@ export type ClientOf<Api extends ApiGuard> = <Route extends keyof Api, Method ex
2348
2348
  query: Endpoint["req"]["query"] extends Record<string, z.ZodSchema<ValidQueryParamTypes>> ? {
2349
2349
  [key in keyof Endpoint["req"]["query"]]: z.infer<Endpoint["req"]["query"][key]>;
2350
2350
  } : undefined;
2351
+ headers: Endpoint["req"]["headers"] extends Record<string, z.ZodSchema<string | undefined>> ? {
2352
+ [key in keyof Endpoint["req"]["headers"]]: z.infer<Endpoint["req"]["headers"][key]>;
2353
+ } : undefined;
2351
2354
  }>) => Promise<z.infer<Endpoint["res"]> | ClientFetchErrors>;
2352
2355
  export type ClientFetchErrors = {
2353
2356
  status: 404;
@@ -71,7 +71,27 @@ export declare function themeCustomProperties(theme: {
71
71
  accent?: string | null;
72
72
  /** A `--radius` length. The caller maps the named step; see `THEME_RADIUS_LENGTHS`. */
73
73
  radius?: string | null;
74
+ /** The proposal colour, a hex. See {@link proposalCustomProperties}. */
75
+ proposal?: string | null;
74
76
  }): Record<string, string>;
77
+ /**
78
+ * The proposal colour's tokens, for light and dark at once.
79
+ *
80
+ * The six `--*-proposal` tokens are declared per mode in `index.css`, each as
81
+ * `var(--theme-proposal-<mode>-<token>, <Val's violet>)`, so the ones written
82
+ * here are picked up where the mode block is declared -- on every element the
83
+ * Studio stamps `data-mode` on, which is where these go (see
84
+ * `themeCustomProperties` on why a `var()` resolves where it is declared).
85
+ * Both modes' values are written because an element does not know which mode
86
+ * its subtree will be in by the time it is styled.
87
+ *
88
+ * From the same ramp as the accent: the hue is the project's, the lightness
89
+ * of each step Val's, so the steps chosen here have the contrast Val's violet
90
+ * had. Text on the filled colour is white unless white would not read, then
91
+ * the ramp's darkest step. Empty for a value that is not a usable hex, so
92
+ * Val's violet stays.
93
+ */
94
+ export declare function proposalCustomProperties(hex: string): Record<string, string>;
75
95
  /**
76
96
  * WCAG relative luminance of a six-digit hex.
77
97
  *
@@ -3755,7 +3755,7 @@ var createValClient = function createValClient(host, config, options) {
3755
3755
  return /*#__PURE__*/function () {
3756
3756
  var _ref = slicedToArray._asyncToGenerator(/*#__PURE__*/slicedToArray._regenerator().m(function _callee2(path, method, req) {
3757
3757
  var _anyApi$path, _apiEndpoint$req$body;
3758
- var anyReq, fullPath, params, _i, _Object$keys, _anyReq$query, key, _anyReq$query2, _iterator, _step, value, _anyReq$query3, _anyReq$query4, apiEndpoint, reqBodyResult, res, _t;
3758
+ var anyReq, fullPath, params, _i, _Object$keys, _anyReq$query, key, _anyReq$query2, _iterator, _step, value, _anyReq$query3, _anyReq$query4, apiEndpoint, reqBodyResult, headers, _i2, _Object$entries, _Object$entries$_i, name, _value, res, _t;
3759
3759
  return slicedToArray._regenerator().w(function (_context2) {
3760
3760
  while (1) switch (_context2.p = _context2.n) {
3761
3761
  case 0:
@@ -3838,13 +3838,22 @@ var createValClient = function createValClient(host, config, options) {
3838
3838
  }
3839
3839
  });
3840
3840
  case 2:
3841
- _context2.p = 2;
3842
- _context2.n = 3;
3841
+ headers = {
3842
+ "Content-Type": "application/json"
3843
+ };
3844
+ if (anyReq !== null && anyReq !== void 0 && anyReq.headers) {
3845
+ for (_i2 = 0, _Object$entries = Object.entries(anyReq.headers); _i2 < _Object$entries.length; _i2++) {
3846
+ _Object$entries$_i = slicedToArray._slicedToArray(_Object$entries[_i2], 2), name = _Object$entries$_i[0], _value = _Object$entries$_i[1];
3847
+ if (typeof _value === "string") {
3848
+ headers[name] = _value;
3849
+ }
3850
+ }
3851
+ }
3852
+ _context2.p = 3;
3853
+ _context2.n = 4;
3843
3854
  return send("".concat(host).concat(fullPath), {
3844
3855
  method: method,
3845
- headers: {
3846
- "Content-Type": "application/json"
3847
- },
3856
+ headers: headers,
3848
3857
  body: anyReq.body !== undefined ? JSON.stringify(anyReq.body) : undefined
3849
3858
  }).then(/*#__PURE__*/function () {
3850
3859
  var _ref2 = slicedToArray._asyncToGenerator(/*#__PURE__*/slicedToArray._regenerator().m(function _callee(res) {
@@ -3936,11 +3945,11 @@ var createValClient = function createValClient(host, config, options) {
3936
3945
  return _ref2.apply(this, arguments);
3937
3946
  };
3938
3947
  }());
3939
- case 3:
3948
+ case 4:
3940
3949
  res = _context2.v;
3941
3950
  return _context2.a(2, res);
3942
- case 4:
3943
- _context2.p = 4;
3951
+ case 5:
3952
+ _context2.p = 5;
3944
3953
  _t = _context2.v;
3945
3954
  return _context2.a(2, {
3946
3955
  status: null,
@@ -3952,7 +3961,7 @@ var createValClient = function createValClient(host, config, options) {
3952
3961
  }
3953
3962
  });
3954
3963
  }
3955
- }, _callee2, null, [[2, 4]]);
3964
+ }, _callee2, null, [[3, 5]]);
3956
3965
  }));
3957
3966
  return function (_x, _x2, _x3) {
3958
3967
  return _ref.apply(this, arguments);
@@ -7521,7 +7530,7 @@ function accentRamp(accent) {
7521
7530
  * Empty when nothing is set, which is what makes "no theme" cost nothing.
7522
7531
  */
7523
7532
  function themeCustomProperties(theme) {
7524
- var properties = {};
7533
+ var properties = createForOfIteratorHelper._objectSpread2({}, theme.proposal ? proposalCustomProperties(theme.proposal) : {});
7525
7534
  if (theme.accent) {
7526
7535
  var ramp = accentRamp(theme.accent);
7527
7536
  if (ramp !== null) {
@@ -7580,6 +7589,50 @@ function themeCustomProperties(theme) {
7580
7589
  return properties;
7581
7590
  }
7582
7591
 
7592
+ /**
7593
+ * The proposal colour's tokens, for light and dark at once.
7594
+ *
7595
+ * The six `--*-proposal` tokens are declared per mode in `index.css`, each as
7596
+ * `var(--theme-proposal-<mode>-<token>, <Val's violet>)`, so the ones written
7597
+ * here are picked up where the mode block is declared -- on every element the
7598
+ * Studio stamps `data-mode` on, which is where these go (see
7599
+ * `themeCustomProperties` on why a `var()` resolves where it is declared).
7600
+ * Both modes' values are written because an element does not know which mode
7601
+ * its subtree will be in by the time it is styled.
7602
+ *
7603
+ * From the same ramp as the accent: the hue is the project's, the lightness
7604
+ * of each step Val's, so the steps chosen here have the contrast Val's violet
7605
+ * had. Text on the filled colour is white unless white would not read, then
7606
+ * the ramp's darkest step. Empty for a value that is not a usable hex, so
7607
+ * Val's violet stays.
7608
+ */
7609
+ function proposalCustomProperties(hex) {
7610
+ var ramp = accentRamp(hex);
7611
+ if (ramp === null) return {};
7612
+ var onFill = function onFill(fill) {
7613
+ return contrastRatio("#ffffff", fill) >= 4.5 ? "#ffffff" : ramp[1000];
7614
+ };
7615
+ var soft = hexToRgb(ramp[500]);
7616
+ var softDark = soft === null ? ramp[900] : "rgba(".concat(soft.map(function (c) {
7617
+ return Math.round(c * 255);
7618
+ }).join(", "), ", 0.16)");
7619
+ return {
7620
+ "--theme-proposal-light-bg": ramp[700],
7621
+ "--theme-proposal-light-bg-hover": ramp[800],
7622
+ "--theme-proposal-light-bg-soft": ramp[100],
7623
+ "--theme-proposal-light-fg": ramp[700],
7624
+ "--theme-proposal-light-fg-on": onFill(ramp[700]),
7625
+ "--theme-proposal-light-border": ramp[400],
7626
+ // 700 in dark too: 600 left white text below AA for some hues.
7627
+ "--theme-proposal-dark-bg": ramp[700],
7628
+ "--theme-proposal-dark-bg-hover": ramp[600],
7629
+ "--theme-proposal-dark-bg-soft": softDark,
7630
+ "--theme-proposal-dark-fg": ramp[300],
7631
+ "--theme-proposal-dark-fg-on": onFill(ramp[700]),
7632
+ "--theme-proposal-dark-border": ramp[700]
7633
+ };
7634
+ }
7635
+
7583
7636
  /**
7584
7637
  * WCAG relative luminance of a six-digit hex.
7585
7638
  *
@@ -8783,6 +8836,7 @@ exports.memoizePerRequest = memoizePerRequest;
8783
8836
  exports.newestCommitSha = newestCommitSha;
8784
8837
  exports.partitionValidationErrors = partitionValidationErrors;
8785
8838
  exports.performSearch = performSearch;
8839
+ exports.proposalCustomProperties = proposalCustomProperties;
8786
8840
  exports.relativeLuminance = relativeLuminance;
8787
8841
  exports.remirrorToRichTextSource = remirrorToRichTextSource;
8788
8842
  exports.removeModule = removeModule;
@@ -3755,7 +3755,7 @@ var createValClient = function createValClient(host, config, options) {
3755
3755
  return /*#__PURE__*/function () {
3756
3756
  var _ref = slicedToArray._asyncToGenerator(/*#__PURE__*/slicedToArray._regenerator().m(function _callee2(path, method, req) {
3757
3757
  var _anyApi$path, _apiEndpoint$req$body;
3758
- var anyReq, fullPath, params, _i, _Object$keys, _anyReq$query, key, _anyReq$query2, _iterator, _step, value, _anyReq$query3, _anyReq$query4, apiEndpoint, reqBodyResult, res, _t;
3758
+ var anyReq, fullPath, params, _i, _Object$keys, _anyReq$query, key, _anyReq$query2, _iterator, _step, value, _anyReq$query3, _anyReq$query4, apiEndpoint, reqBodyResult, headers, _i2, _Object$entries, _Object$entries$_i, name, _value, res, _t;
3759
3759
  return slicedToArray._regenerator().w(function (_context2) {
3760
3760
  while (1) switch (_context2.p = _context2.n) {
3761
3761
  case 0:
@@ -3838,13 +3838,22 @@ var createValClient = function createValClient(host, config, options) {
3838
3838
  }
3839
3839
  });
3840
3840
  case 2:
3841
- _context2.p = 2;
3842
- _context2.n = 3;
3841
+ headers = {
3842
+ "Content-Type": "application/json"
3843
+ };
3844
+ if (anyReq !== null && anyReq !== void 0 && anyReq.headers) {
3845
+ for (_i2 = 0, _Object$entries = Object.entries(anyReq.headers); _i2 < _Object$entries.length; _i2++) {
3846
+ _Object$entries$_i = slicedToArray._slicedToArray(_Object$entries[_i2], 2), name = _Object$entries$_i[0], _value = _Object$entries$_i[1];
3847
+ if (typeof _value === "string") {
3848
+ headers[name] = _value;
3849
+ }
3850
+ }
3851
+ }
3852
+ _context2.p = 3;
3853
+ _context2.n = 4;
3843
3854
  return send("".concat(host).concat(fullPath), {
3844
3855
  method: method,
3845
- headers: {
3846
- "Content-Type": "application/json"
3847
- },
3856
+ headers: headers,
3848
3857
  body: anyReq.body !== undefined ? JSON.stringify(anyReq.body) : undefined
3849
3858
  }).then(/*#__PURE__*/function () {
3850
3859
  var _ref2 = slicedToArray._asyncToGenerator(/*#__PURE__*/slicedToArray._regenerator().m(function _callee(res) {
@@ -3936,11 +3945,11 @@ var createValClient = function createValClient(host, config, options) {
3936
3945
  return _ref2.apply(this, arguments);
3937
3946
  };
3938
3947
  }());
3939
- case 3:
3948
+ case 4:
3940
3949
  res = _context2.v;
3941
3950
  return _context2.a(2, res);
3942
- case 4:
3943
- _context2.p = 4;
3951
+ case 5:
3952
+ _context2.p = 5;
3944
3953
  _t = _context2.v;
3945
3954
  return _context2.a(2, {
3946
3955
  status: null,
@@ -3952,7 +3961,7 @@ var createValClient = function createValClient(host, config, options) {
3952
3961
  }
3953
3962
  });
3954
3963
  }
3955
- }, _callee2, null, [[2, 4]]);
3964
+ }, _callee2, null, [[3, 5]]);
3956
3965
  }));
3957
3966
  return function (_x, _x2, _x3) {
3958
3967
  return _ref.apply(this, arguments);
@@ -7521,7 +7530,7 @@ function accentRamp(accent) {
7521
7530
  * Empty when nothing is set, which is what makes "no theme" cost nothing.
7522
7531
  */
7523
7532
  function themeCustomProperties(theme) {
7524
- var properties = {};
7533
+ var properties = createForOfIteratorHelper._objectSpread2({}, theme.proposal ? proposalCustomProperties(theme.proposal) : {});
7525
7534
  if (theme.accent) {
7526
7535
  var ramp = accentRamp(theme.accent);
7527
7536
  if (ramp !== null) {
@@ -7580,6 +7589,50 @@ function themeCustomProperties(theme) {
7580
7589
  return properties;
7581
7590
  }
7582
7591
 
7592
+ /**
7593
+ * The proposal colour's tokens, for light and dark at once.
7594
+ *
7595
+ * The six `--*-proposal` tokens are declared per mode in `index.css`, each as
7596
+ * `var(--theme-proposal-<mode>-<token>, <Val's violet>)`, so the ones written
7597
+ * here are picked up where the mode block is declared -- on every element the
7598
+ * Studio stamps `data-mode` on, which is where these go (see
7599
+ * `themeCustomProperties` on why a `var()` resolves where it is declared).
7600
+ * Both modes' values are written because an element does not know which mode
7601
+ * its subtree will be in by the time it is styled.
7602
+ *
7603
+ * From the same ramp as the accent: the hue is the project's, the lightness
7604
+ * of each step Val's, so the steps chosen here have the contrast Val's violet
7605
+ * had. Text on the filled colour is white unless white would not read, then
7606
+ * the ramp's darkest step. Empty for a value that is not a usable hex, so
7607
+ * Val's violet stays.
7608
+ */
7609
+ function proposalCustomProperties(hex) {
7610
+ var ramp = accentRamp(hex);
7611
+ if (ramp === null) return {};
7612
+ var onFill = function onFill(fill) {
7613
+ return contrastRatio("#ffffff", fill) >= 4.5 ? "#ffffff" : ramp[1000];
7614
+ };
7615
+ var soft = hexToRgb(ramp[500]);
7616
+ var softDark = soft === null ? ramp[900] : "rgba(".concat(soft.map(function (c) {
7617
+ return Math.round(c * 255);
7618
+ }).join(", "), ", 0.16)");
7619
+ return {
7620
+ "--theme-proposal-light-bg": ramp[700],
7621
+ "--theme-proposal-light-bg-hover": ramp[800],
7622
+ "--theme-proposal-light-bg-soft": ramp[100],
7623
+ "--theme-proposal-light-fg": ramp[700],
7624
+ "--theme-proposal-light-fg-on": onFill(ramp[700]),
7625
+ "--theme-proposal-light-border": ramp[400],
7626
+ // 700 in dark too: 600 left white text below AA for some hues.
7627
+ "--theme-proposal-dark-bg": ramp[700],
7628
+ "--theme-proposal-dark-bg-hover": ramp[600],
7629
+ "--theme-proposal-dark-bg-soft": softDark,
7630
+ "--theme-proposal-dark-fg": ramp[300],
7631
+ "--theme-proposal-dark-fg-on": onFill(ramp[700]),
7632
+ "--theme-proposal-dark-border": ramp[700]
7633
+ };
7634
+ }
7635
+
7583
7636
  /**
7584
7637
  * WCAG relative luminance of a six-digit hex.
7585
7638
  *
@@ -8783,6 +8836,7 @@ exports.memoizePerRequest = memoizePerRequest;
8783
8836
  exports.newestCommitSha = newestCommitSha;
8784
8837
  exports.partitionValidationErrors = partitionValidationErrors;
8785
8838
  exports.performSearch = performSearch;
8839
+ exports.proposalCustomProperties = proposalCustomProperties;
8786
8840
  exports.relativeLuminance = relativeLuminance;
8787
8841
  exports.remirrorToRichTextSource = remirrorToRichTextSource;
8788
8842
  exports.removeModule = removeModule;
@@ -3748,7 +3748,7 @@ var createValClient = function createValClient(host, config, options) {
3748
3748
  return /*#__PURE__*/function () {
3749
3749
  var _ref = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2(path, method, req) {
3750
3750
  var _anyApi$path, _apiEndpoint$req$body;
3751
- var anyReq, fullPath, params, _i, _Object$keys, _anyReq$query, key, _anyReq$query2, _iterator, _step, value, _anyReq$query3, _anyReq$query4, apiEndpoint, reqBodyResult, res, _t;
3751
+ var anyReq, fullPath, params, _i, _Object$keys, _anyReq$query, key, _anyReq$query2, _iterator, _step, value, _anyReq$query3, _anyReq$query4, apiEndpoint, reqBodyResult, headers, _i2, _Object$entries, _Object$entries$_i, name, _value, res, _t;
3752
3752
  return _regenerator().w(function (_context2) {
3753
3753
  while (1) switch (_context2.p = _context2.n) {
3754
3754
  case 0:
@@ -3831,13 +3831,22 @@ var createValClient = function createValClient(host, config, options) {
3831
3831
  }
3832
3832
  });
3833
3833
  case 2:
3834
- _context2.p = 2;
3835
- _context2.n = 3;
3834
+ headers = {
3835
+ "Content-Type": "application/json"
3836
+ };
3837
+ if (anyReq !== null && anyReq !== void 0 && anyReq.headers) {
3838
+ for (_i2 = 0, _Object$entries = Object.entries(anyReq.headers); _i2 < _Object$entries.length; _i2++) {
3839
+ _Object$entries$_i = _slicedToArray(_Object$entries[_i2], 2), name = _Object$entries$_i[0], _value = _Object$entries$_i[1];
3840
+ if (typeof _value === "string") {
3841
+ headers[name] = _value;
3842
+ }
3843
+ }
3844
+ }
3845
+ _context2.p = 3;
3846
+ _context2.n = 4;
3836
3847
  return send("".concat(host).concat(fullPath), {
3837
3848
  method: method,
3838
- headers: {
3839
- "Content-Type": "application/json"
3840
- },
3849
+ headers: headers,
3841
3850
  body: anyReq.body !== undefined ? JSON.stringify(anyReq.body) : undefined
3842
3851
  }).then(/*#__PURE__*/function () {
3843
3852
  var _ref2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee(res) {
@@ -3929,11 +3938,11 @@ var createValClient = function createValClient(host, config, options) {
3929
3938
  return _ref2.apply(this, arguments);
3930
3939
  };
3931
3940
  }());
3932
- case 3:
3941
+ case 4:
3933
3942
  res = _context2.v;
3934
3943
  return _context2.a(2, res);
3935
- case 4:
3936
- _context2.p = 4;
3944
+ case 5:
3945
+ _context2.p = 5;
3937
3946
  _t = _context2.v;
3938
3947
  return _context2.a(2, {
3939
3948
  status: null,
@@ -3945,7 +3954,7 @@ var createValClient = function createValClient(host, config, options) {
3945
3954
  }
3946
3955
  });
3947
3956
  }
3948
- }, _callee2, null, [[2, 4]]);
3957
+ }, _callee2, null, [[3, 5]]);
3949
3958
  }));
3950
3959
  return function (_x, _x2, _x3) {
3951
3960
  return _ref.apply(this, arguments);
@@ -7514,7 +7523,7 @@ function accentRamp(accent) {
7514
7523
  * Empty when nothing is set, which is what makes "no theme" cost nothing.
7515
7524
  */
7516
7525
  function themeCustomProperties(theme) {
7517
- var properties = {};
7526
+ var properties = _objectSpread2({}, theme.proposal ? proposalCustomProperties(theme.proposal) : {});
7518
7527
  if (theme.accent) {
7519
7528
  var ramp = accentRamp(theme.accent);
7520
7529
  if (ramp !== null) {
@@ -7573,6 +7582,50 @@ function themeCustomProperties(theme) {
7573
7582
  return properties;
7574
7583
  }
7575
7584
 
7585
+ /**
7586
+ * The proposal colour's tokens, for light and dark at once.
7587
+ *
7588
+ * The six `--*-proposal` tokens are declared per mode in `index.css`, each as
7589
+ * `var(--theme-proposal-<mode>-<token>, <Val's violet>)`, so the ones written
7590
+ * here are picked up where the mode block is declared -- on every element the
7591
+ * Studio stamps `data-mode` on, which is where these go (see
7592
+ * `themeCustomProperties` on why a `var()` resolves where it is declared).
7593
+ * Both modes' values are written because an element does not know which mode
7594
+ * its subtree will be in by the time it is styled.
7595
+ *
7596
+ * From the same ramp as the accent: the hue is the project's, the lightness
7597
+ * of each step Val's, so the steps chosen here have the contrast Val's violet
7598
+ * had. Text on the filled colour is white unless white would not read, then
7599
+ * the ramp's darkest step. Empty for a value that is not a usable hex, so
7600
+ * Val's violet stays.
7601
+ */
7602
+ function proposalCustomProperties(hex) {
7603
+ var ramp = accentRamp(hex);
7604
+ if (ramp === null) return {};
7605
+ var onFill = function onFill(fill) {
7606
+ return contrastRatio("#ffffff", fill) >= 4.5 ? "#ffffff" : ramp[1000];
7607
+ };
7608
+ var soft = hexToRgb(ramp[500]);
7609
+ var softDark = soft === null ? ramp[900] : "rgba(".concat(soft.map(function (c) {
7610
+ return Math.round(c * 255);
7611
+ }).join(", "), ", 0.16)");
7612
+ return {
7613
+ "--theme-proposal-light-bg": ramp[700],
7614
+ "--theme-proposal-light-bg-hover": ramp[800],
7615
+ "--theme-proposal-light-bg-soft": ramp[100],
7616
+ "--theme-proposal-light-fg": ramp[700],
7617
+ "--theme-proposal-light-fg-on": onFill(ramp[700]),
7618
+ "--theme-proposal-light-border": ramp[400],
7619
+ // 700 in dark too: 600 left white text below AA for some hues.
7620
+ "--theme-proposal-dark-bg": ramp[700],
7621
+ "--theme-proposal-dark-bg-hover": ramp[600],
7622
+ "--theme-proposal-dark-bg-soft": softDark,
7623
+ "--theme-proposal-dark-fg": ramp[300],
7624
+ "--theme-proposal-dark-fg-on": onFill(ramp[700]),
7625
+ "--theme-proposal-dark-border": ramp[700]
7626
+ };
7627
+ }
7628
+
7576
7629
  /**
7577
7630
  * WCAG relative luminance of a six-digit hex.
7578
7631
  *
@@ -8599,4 +8652,4 @@ var messageOf = function messageOf(error) {
8599
8652
  return error instanceof Error ? error.message : String(error);
8600
8653
  };
8601
8654
 
8602
- export { AA_LARGE, AA_TEXT, AnalyticsBeacon, Api, BRAND_CONTRAST_PAIRS, BinaryFileRef, CodeOptions, ColorOptions, DEFAULT_ERROR_MESSAGE, DateOptions, ENCODE_DEFAULTS, ENCODE_MIME_TYPE_OF, FileOptions, HistoricalCommit, HistoricalModule, HistoricalPatchSet, HistoryError, ImageEncodeOption, ImageOptions, JSONValue, JSON_ENTRIES_BATCH_MAX, LOCAL_FILE_IN_REMOTE_PROJECT_HINT, LOCAL_FILE_IN_REMOTE_PROJECT_WARNING, ModuleComparison, NEVER_ENCODED, ParentRef$1 as ParentRef, Patch, PatchBlock, PatchId, PatchJSON, PatchSets, PlanRefusalError, RAMP_STEPS, RemirrorBr, RemirrorBulletList, RemirrorHeading, RemirrorImage, RemirrorJSON, RemirrorLinkMark, RemirrorListItem, RemirrorOrderedList, RemirrorParagraph, RemirrorText, RemirrorTextMark, RestoreVerdict, RichTextOptions, SCHEMA_SOURCE_FIXES, SELF_CHECK_VERSION, STUDIO_FIXES, SerializedArraySchema, SerializedBooleanSchema, SerializedCodeSchema, SerializedColorSchema, SerializedDateSchema, SerializedDateTimeSchema, SerializedDiscriminatedUnionSchema, SerializedEnumSchema, SerializedFileSchema, SerializedImageSchema, SerializedKeyOfSchema, SerializedLiteralSchema, SerializedLocaleSchema, SerializedNumberSchema, SerializedObjectSchema, SerializedRecordSchema, SerializedRichTextSchema, SerializedRouteSchema, SerializedSchema, SerializedSettingsSchema, SerializedStringSchema, SerializedValViewSchema, SerializedVideoSchema, SharedValConfig, VAL_ENABLE_COOKIE_NAME, VAL_GREEN_RAMP, VAL_SESSION_COOKIE, VAL_STATE_COOKIE, VAL_STUDIO_HEADER, ValCommit, ValDeployment, VideoOptions, VideoStreamOption, WARNING_FIXES, WASM_ENCODED_MIME_TYPES, accentRamp, buildDuplicatePatch, buildEmptyAtPathPatch, buildFileRefValue, buildImageGalleryPatch, buildRemoveImageGalleryEntryPatch, buildSearchIndex, chainHeadOf, checkCompatibility, chooseEncoded, concatModulePath, contrastRatio, createRegExpFromPattern, createSearchIndex, createValClient, declaredLocales, describeContainerAtPath, emptyOf, enumLocaleTag, explainIncompatible, fallbackMimeType, filterBlockingValidationErrors, filterRoutesByPatterns, findSimilar, fitWithin, flattenRichText, forEachRichTextImage, getErrorMessageFromUnknownJson, getFilenameFromRef, getInlineImgInfo, getKeyOfRecordAt, getRefParts, getRoutesOf, getRoutesWithModulePaths, getSourceAt, getValDemo, indexModule, isInsidePatchSetPath, isLocaleSchema, isMimeTypeAccepted, isRemoteSchema, isRepairedOnSave, isSchemaSourceFixError, isSkippedSource, isStudioFix, isValidationWarning, isWarningFix, joinSharedChanges, keyOfRecordPath, levenshtein, localeAt, localeMeantBy, memoizePerRequest, newestCommitSha, partitionValidationErrors, performSearch, relativeLuminance, remirrorToRichTextSource, removeModule, resolveEncodeSettings, resolvePairGround, resolveSchemaSourceFixForError, resolveSchemaSourceFixes, resolveSerializedSchemaAtPath, richTextImageSchema, richTextToRemirror, safeParsePatch, schemaErrorsOf, schemaTypesOfPath, selectionClosure, selfCheck, shouldEncodeWithWasm, sideFiles, sideSource, sourcePathOfChild, themeCustomProperties, toolNames, traverseSchemaSource, urlOf, validateRoutePatterns, withExtension };
8655
+ export { AA_LARGE, AA_TEXT, AnalyticsBeacon, Api, BRAND_CONTRAST_PAIRS, BinaryFileRef, CodeOptions, ColorOptions, DEFAULT_ERROR_MESSAGE, DateOptions, ENCODE_DEFAULTS, ENCODE_MIME_TYPE_OF, FileOptions, HistoricalCommit, HistoricalModule, HistoricalPatchSet, HistoryError, ImageEncodeOption, ImageOptions, JSONValue, JSON_ENTRIES_BATCH_MAX, LOCAL_FILE_IN_REMOTE_PROJECT_HINT, LOCAL_FILE_IN_REMOTE_PROJECT_WARNING, ModuleComparison, NEVER_ENCODED, ParentRef$1 as ParentRef, Patch, PatchBlock, PatchId, PatchJSON, PatchSets, PlanRefusalError, RAMP_STEPS, RemirrorBr, RemirrorBulletList, RemirrorHeading, RemirrorImage, RemirrorJSON, RemirrorLinkMark, RemirrorListItem, RemirrorOrderedList, RemirrorParagraph, RemirrorText, RemirrorTextMark, RestoreVerdict, RichTextOptions, SCHEMA_SOURCE_FIXES, SELF_CHECK_VERSION, STUDIO_FIXES, SerializedArraySchema, SerializedBooleanSchema, SerializedCodeSchema, SerializedColorSchema, SerializedDateSchema, SerializedDateTimeSchema, SerializedDiscriminatedUnionSchema, SerializedEnumSchema, SerializedFileSchema, SerializedImageSchema, SerializedKeyOfSchema, SerializedLiteralSchema, SerializedLocaleSchema, SerializedNumberSchema, SerializedObjectSchema, SerializedRecordSchema, SerializedRichTextSchema, SerializedRouteSchema, SerializedSchema, SerializedSettingsSchema, SerializedStringSchema, SerializedValViewSchema, SerializedVideoSchema, SharedValConfig, VAL_ENABLE_COOKIE_NAME, VAL_GREEN_RAMP, VAL_SESSION_COOKIE, VAL_STATE_COOKIE, VAL_STUDIO_HEADER, ValCommit, ValDeployment, VideoOptions, VideoStreamOption, WARNING_FIXES, WASM_ENCODED_MIME_TYPES, accentRamp, buildDuplicatePatch, buildEmptyAtPathPatch, buildFileRefValue, buildImageGalleryPatch, buildRemoveImageGalleryEntryPatch, buildSearchIndex, chainHeadOf, checkCompatibility, chooseEncoded, concatModulePath, contrastRatio, createRegExpFromPattern, createSearchIndex, createValClient, declaredLocales, describeContainerAtPath, emptyOf, enumLocaleTag, explainIncompatible, fallbackMimeType, filterBlockingValidationErrors, filterRoutesByPatterns, findSimilar, fitWithin, flattenRichText, forEachRichTextImage, getErrorMessageFromUnknownJson, getFilenameFromRef, getInlineImgInfo, getKeyOfRecordAt, getRefParts, getRoutesOf, getRoutesWithModulePaths, getSourceAt, getValDemo, indexModule, isInsidePatchSetPath, isLocaleSchema, isMimeTypeAccepted, isRemoteSchema, isRepairedOnSave, isSchemaSourceFixError, isSkippedSource, isStudioFix, isValidationWarning, isWarningFix, joinSharedChanges, keyOfRecordPath, levenshtein, localeAt, localeMeantBy, memoizePerRequest, newestCommitSha, partitionValidationErrors, performSearch, proposalCustomProperties, relativeLuminance, remirrorToRichTextSource, removeModule, resolveEncodeSettings, resolvePairGround, resolveSchemaSourceFixForError, resolveSchemaSourceFixes, resolveSerializedSchemaAtPath, richTextImageSchema, richTextToRemirror, safeParsePatch, schemaErrorsOf, schemaTypesOfPath, selectionClosure, selfCheck, shouldEncodeWithWasm, sideFiles, sideSource, sourcePathOfChild, themeCustomProperties, toolNames, traverseSchemaSource, urlOf, validateRoutePatterns, withExtension };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@valbuild/shared",
3
- "version": "0.150.1",
3
+ "version": "0.150.3",
4
4
  "private": false,
5
5
  "description": "Val shared types and utilities",
6
6
  "repository": {
@@ -53,7 +53,7 @@
53
53
  "yaml": "^2.9.0",
54
54
  "zod": "^4.4.3",
55
55
  "zod-validation-error": "^5.0.0",
56
- "@valbuild/core": "0.150.1"
56
+ "@valbuild/core": "0.150.3"
57
57
  },
58
58
  "files": [
59
59
  "CHANGELOG.md",