@rulecms/source-components-angular 0.1.0 → 0.3.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.
Files changed (41) hide show
  1. package/README.md +1 -0
  2. package/fesm2022/rulecms-source-components-angular.mjs +553 -89
  3. package/fesm2022/rulecms-source-components-angular.mjs.map +1 -1
  4. package/lib/base-components/display/card-entries/card-entries.d.ts.map +1 -1
  5. package/lib/base-components/display/component-attributes/component-name-to-modify-attribute.d.ts.map +1 -1
  6. package/lib/base-components/display/components/r-button/button-css-variables.d.ts +12 -0
  7. package/lib/base-components/display/components/r-button/button-css-variables.d.ts.map +1 -1
  8. package/lib/base-components/display/components/r-button/button-library-stylesheet.d.ts +16 -0
  9. package/lib/base-components/display/components/r-button/button-library-stylesheet.d.ts.map +1 -0
  10. package/lib/base-components/display/components/r-button/button-preset-styles.d.ts +17 -1
  11. package/lib/base-components/display/components/r-button/button-preset-styles.d.ts.map +1 -1
  12. package/lib/base-components/display/components/r-button/button-presets.d.ts +3 -4
  13. package/lib/base-components/display/components/r-button/button-presets.d.ts.map +1 -1
  14. package/lib/base-components/display/components/r-button/r-button.component.d.ts +1 -1
  15. package/lib/base-components/display/components/r-button/r-button.component.d.ts.map +1 -1
  16. package/lib/base-components/display/components/r-mount/attribute-edit-mode-configs.d.ts +6 -0
  17. package/lib/base-components/display/components/r-mount/attribute-edit-mode-configs.d.ts.map +1 -0
  18. package/lib/base-components/display/components/r-mount/default-attribute-values.d.ts +8 -0
  19. package/lib/base-components/display/components/r-mount/default-attribute-values.d.ts.map +1 -0
  20. package/lib/base-components/display/components/r-mount/display-card-entry.d.ts +3 -0
  21. package/lib/base-components/display/components/r-mount/display-card-entry.d.ts.map +1 -0
  22. package/lib/base-components/display/components/r-mount/mount-attributes.d.ts +34 -0
  23. package/lib/base-components/display/components/r-mount/mount-attributes.d.ts.map +1 -0
  24. package/lib/base-components/display/components/r-mount/r-mount.component.d.ts +31 -0
  25. package/lib/base-components/display/components/r-mount/r-mount.component.d.ts.map +1 -0
  26. package/lib/base-components/display/components/r-mount/resolve-mount-render.d.ts +26 -0
  27. package/lib/base-components/display/components/r-mount/resolve-mount-render.d.ts.map +1 -0
  28. package/lib/base-components/display/components/r-mount/resolve-no-container.d.ts +7 -0
  29. package/lib/base-components/display/components/r-mount/resolve-no-container.d.ts.map +1 -0
  30. package/lib/base-components/display/components/r-mount/resolve-renders-own-element.d.ts +6 -0
  31. package/lib/base-components/display/components/r-mount/resolve-renders-own-element.d.ts.map +1 -0
  32. package/lib/base-components/editor-preview/card-entries/card-entries.d.ts.map +1 -1
  33. package/lib/component-identifiers.d.ts +1 -1
  34. package/lib/component-identifiers.d.ts.map +1 -1
  35. package/lib/component-library-module.d.ts +6 -0
  36. package/lib/component-library-module.d.ts.map +1 -1
  37. package/lib/types.d.ts +3 -0
  38. package/lib/types.d.ts.map +1 -1
  39. package/package.json +2 -2
  40. package/public-api.d.ts +6 -3
  41. package/public-api.d.ts.map +1 -1
@@ -1,10 +1,10 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { Input, Component, ViewChild } from '@angular/core';
3
- import { NgStyle } from '@angular/common';
3
+ import { NgStyle, NgComponentOutlet } from '@angular/common';
4
4
  import * as i1 from '@angular/platform-browser';
5
5
 
6
6
  const DEFAULT_CONTENT_TEXT = 'This is a text block. Click to edit and add your own content.';
7
- const defaultAttributeValues$8 = [
7
+ const defaultAttributeValues$9 = [
8
8
  {
9
9
  name: 'content-text-3-resolutions',
10
10
  defaultValues: {
@@ -695,7 +695,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
695
695
  * - Block tag (`p`, `div`, `h1`, `section`, …): RText puts styleProps on the
696
696
  * tag itself → no wrapper, one less element in the DOM.
697
697
  */
698
- const resolveNoContainer$8 = ({ componentAttributes, }) => !isBlockEnclosingTag(resolveEnclosingTag(componentAttributes));
698
+ const resolveNoContainer$9 = ({ componentAttributes, }) => !isBlockEnclosingTag(resolveEnclosingTag(componentAttributes));
699
699
 
700
700
  /**
701
701
  * True when RText is about to render an element that can carry a className —
@@ -705,9 +705,9 @@ const resolveNoContainer$8 = ({ componentAttributes, }) => !isBlockEnclosingTag(
705
705
  * disagreed with what the component renders, a class would either land on
706
706
  * nothing or force a redundant wrapper.
707
707
  */
708
- const resolveRendersOwnElement$8 = ({ componentAttributes, }) => !!resolveEnclosingTag(componentAttributes);
708
+ const resolveRendersOwnElement$9 = ({ componentAttributes, }) => !!resolveEnclosingTag(componentAttributes);
709
709
 
710
- const attributeEditModeConfigs$8 = [
710
+ const attributeEditModeConfigs$9 = [
711
711
  {
712
712
  name: 'content-text-3-resolutions',
713
713
  defaultValues: {},
@@ -737,15 +737,16 @@ const ComponentIdentifiers = {
737
737
  rEmbed: 'r-embed',
738
738
  rList: 'r-list',
739
739
  rAccordion: 'r-accordion',
740
+ rMount: 'r-mount',
740
741
  };
741
742
 
742
- const displayCardEntry$8 = {
743
+ const displayCardEntry$9 = {
743
744
  id: ComponentIdentifiers.rText,
744
- resolveNoContainer: resolveNoContainer$8,
745
- resolveRendersOwnElement: resolveRendersOwnElement$8,
745
+ resolveNoContainer: resolveNoContainer$9,
746
+ resolveRendersOwnElement: resolveRendersOwnElement$9,
746
747
  card: RTextComponent,
747
- defaultAttributeValues: defaultAttributeValues$8,
748
- attributeEditModeConfigs: attributeEditModeConfigs$8,
748
+ defaultAttributeValues: defaultAttributeValues$9,
749
+ attributeEditModeConfigs: attributeEditModeConfigs$9,
749
750
  };
750
751
 
751
752
  // Builds Cloudinary delivery URLs directly so the component renders a complete
@@ -930,15 +931,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
930
931
  * only add a redundant element. There is no configuration that changes this,
931
932
  * so the answer is the same for every render.
932
933
  */
933
- const resolveNoContainer$7 = () => false;
934
+ const resolveNoContainer$8 = () => false;
934
935
 
935
936
  /**
936
937
  * Always renders an `<img>`, which can carry a className. There is no
937
938
  * configuration that changes this.
938
939
  */
939
- const resolveRendersOwnElement$7 = () => true;
940
+ const resolveRendersOwnElement$8 = () => true;
940
941
 
941
- const defaultAttributeValues$7 = [
942
+ const defaultAttributeValues$8 = [
942
943
  {
943
944
  name: 'cloudinary-cloud-name',
944
945
  defaultValues: {},
@@ -983,7 +984,7 @@ const defaultAttributeValues$7 = [
983
984
  },
984
985
  ];
985
986
 
986
- const attributeEditModeConfigs$7 = [
987
+ const attributeEditModeConfigs$8 = [
987
988
  {
988
989
  name: 'cloudinary-cloud-name',
989
990
  heading: 'Cloudinary Cloud Name',
@@ -1050,13 +1051,13 @@ const attributeEditModeConfigs$7 = [
1050
1051
  },
1051
1052
  ];
1052
1053
 
1053
- const displayCardEntry$7 = {
1054
+ const displayCardEntry$8 = {
1054
1055
  id: ComponentIdentifiers.cloudinaryAdvancedImage,
1055
- resolveNoContainer: resolveNoContainer$7,
1056
- resolveRendersOwnElement: resolveRendersOwnElement$7,
1056
+ resolveNoContainer: resolveNoContainer$8,
1057
+ resolveRendersOwnElement: resolveRendersOwnElement$8,
1057
1058
  card: CloudinaryAdvancedImageComponent,
1058
- defaultAttributeValues: defaultAttributeValues$7,
1059
- attributeEditModeConfigs: attributeEditModeConfigs$7,
1059
+ defaultAttributeValues: defaultAttributeValues$8,
1060
+ attributeEditModeConfigs: attributeEditModeConfigs$8,
1060
1061
  };
1061
1062
 
1062
1063
  // Builds media-host delivery URLs directly so the component renders a complete
@@ -1271,15 +1272,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
1271
1272
  * only add a redundant element. There is no configuration that changes this,
1272
1273
  * so the answer is the same for every render.
1273
1274
  */
1274
- const resolveNoContainer$6 = () => false;
1275
+ const resolveNoContainer$7 = () => false;
1275
1276
 
1276
1277
  /**
1277
1278
  * Always renders a `<video>`, which can carry a className. There is no
1278
1279
  * configuration that changes this.
1279
1280
  */
1280
- const resolveRendersOwnElement$6 = () => true;
1281
+ const resolveRendersOwnElement$7 = () => true;
1281
1282
 
1282
- const defaultAttributeValues$6 = [
1283
+ const defaultAttributeValues$7 = [
1283
1284
  {
1284
1285
  name: 'video-host-cloud-name',
1285
1286
  defaultValues: {},
@@ -1336,7 +1337,7 @@ const defaultAttributeValues$6 = [
1336
1337
  },
1337
1338
  ];
1338
1339
 
1339
- const attributeEditModeConfigs$6 = [
1340
+ const attributeEditModeConfigs$7 = [
1340
1341
  {
1341
1342
  name: 'video-host-cloud-name',
1342
1343
  heading: 'Video Host Cloud Name',
@@ -1421,13 +1422,13 @@ const attributeEditModeConfigs$6 = [
1421
1422
  },
1422
1423
  ];
1423
1424
 
1424
- const displayCardEntry$6 = {
1425
+ const displayCardEntry$7 = {
1425
1426
  id: ComponentIdentifiers.rVideo,
1426
- resolveNoContainer: resolveNoContainer$6,
1427
- resolveRendersOwnElement: resolveRendersOwnElement$6,
1427
+ resolveNoContainer: resolveNoContainer$7,
1428
+ resolveRendersOwnElement: resolveRendersOwnElement$7,
1428
1429
  card: RVideoComponent,
1429
- defaultAttributeValues: defaultAttributeValues$6,
1430
- attributeEditModeConfigs: attributeEditModeConfigs$6,
1430
+ defaultAttributeValues: defaultAttributeValues$7,
1431
+ attributeEditModeConfigs: attributeEditModeConfigs$7,
1431
1432
  };
1432
1433
 
1433
1434
  /**
@@ -1635,16 +1636,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
1635
1636
  * and colour (via currentColor) directly, so a wrapper div would only add a
1636
1637
  * redundant element. No configuration changes that.
1637
1638
  */
1638
- const resolveNoContainer$5 = () => false;
1639
+ const resolveNoContainer$6 = () => false;
1639
1640
 
1640
1641
  /**
1641
1642
  * The `<svg>` carries the className. An unresolvable attribute renders no
1642
1643
  * element at all, but that is a data error rather than a different root type,
1643
1644
  * so the configured happy path is what this answers for.
1644
1645
  */
1645
- const resolveRendersOwnElement$5 = () => true;
1646
+ const resolveRendersOwnElement$6 = () => true;
1646
1647
 
1647
- const defaultAttributeValues$5 = [
1648
+ const defaultAttributeValues$6 = [
1648
1649
  {
1649
1650
  // Holds `{ name, iconNode }`, not a bare name: the composer stamps the
1650
1651
  // geometry when the author picks the icon so the render path never needs
@@ -1656,7 +1657,7 @@ const defaultAttributeValues$5 = [
1656
1657
  },
1657
1658
  ];
1658
1659
 
1659
- const attributeEditModeConfigs$5 = [
1660
+ const attributeEditModeConfigs$6 = [
1660
1661
  {
1661
1662
  name: 'icon-name-3-resolutions',
1662
1663
  heading: 'Icon',
@@ -1667,13 +1668,13 @@ const attributeEditModeConfigs$5 = [
1667
1668
  },
1668
1669
  ];
1669
1670
 
1670
- const displayCardEntry$5 = {
1671
+ const displayCardEntry$6 = {
1671
1672
  id: ComponentIdentifiers.rIcon,
1672
- resolveNoContainer: resolveNoContainer$5,
1673
- resolveRendersOwnElement: resolveRendersOwnElement$5,
1673
+ resolveNoContainer: resolveNoContainer$6,
1674
+ resolveRendersOwnElement: resolveRendersOwnElement$6,
1674
1675
  card: RIconComponent,
1675
- defaultAttributeValues: defaultAttributeValues$5,
1676
- attributeEditModeConfigs: attributeEditModeConfigs$5,
1676
+ defaultAttributeValues: defaultAttributeValues$6,
1677
+ attributeEditModeConfigs: attributeEditModeConfigs$6,
1677
1678
  };
1678
1679
 
1679
1680
  /**
@@ -1846,6 +1847,18 @@ const SIZE_SCALES = {
1846
1847
  * button to differ still override it per column, as before.
1847
1848
  */
1848
1849
  const BUTTON_CSS_VARIABLE_PREFIX = '--rulecms-button';
1850
+ /**
1851
+ * Per-instance slots the library stylesheet reads. The preset writes these on
1852
+ * the element; a column `backgroundColor` rewrite and a future widget-level
1853
+ * token both land on the same names.
1854
+ */
1855
+ const BUTTON_FILL_VARIABLE = `${BUTTON_CSS_VARIABLE_PREFIX}-fill`;
1856
+ const BUTTON_FILL_HOVER_VARIABLE = `${BUTTON_CSS_VARIABLE_PREFIX}-fill-hover`;
1857
+ const BUTTON_FILL_ACTIVE_VARIABLE = `${BUTTON_CSS_VARIABLE_PREFIX}-fill-active`;
1858
+ const BUTTON_INK_VARIABLE = `${BUTTON_CSS_VARIABLE_PREFIX}-ink`;
1859
+ const BUTTON_INK_HOVER_VARIABLE = `${BUTTON_CSS_VARIABLE_PREFIX}-ink-hover`;
1860
+ const BUTTON_BORDER_VARIABLE = `${BUTTON_CSS_VARIABLE_PREFIX}-border`;
1861
+ const BUTTON_RING_VARIABLE = `${BUTTON_CSS_VARIABLE_PREFIX}-ring`;
1849
1862
  const toneCssVariable = (tone, slot = '') => slot === ''
1850
1863
  ? `${BUTTON_CSS_VARIABLE_PREFIX}-${tone}`
1851
1864
  : `${BUTTON_CSS_VARIABLE_PREFIX}-${tone}-${slot}`;
@@ -1857,6 +1870,7 @@ const cssVarWithFallback = (variableName, fallback) => `var(${variableName}, ${f
1857
1870
  /** Shorthand for the common case: one tone slot with its palette default. */
1858
1871
  const toneColor = (tone, slot, fallback) => cssVarWithFallback(toneCssVariable(tone, slot), fallback);
1859
1872
 
1873
+ const asVars = (vars) => vars;
1860
1874
  /**
1861
1875
  * The rules that stop a native `<button>` looking like a native `<button>`.
1862
1876
  *
@@ -1884,9 +1898,7 @@ const structuralStyles = {
1884
1898
  fontFamily: 'inherit',
1885
1899
  fontWeight: 600,
1886
1900
  lineHeight: 1.25,
1887
- // Inert until something changes state. Kept because the host's own `:hover`
1888
- // rule — the only hover mechanism available to a widget today — then eases
1889
- // for free instead of snapping.
1901
+ // Eases the library stylesheet's :hover / :active colour change.
1890
1902
  transition: 'background-color 150ms ease, border-color 150ms ease, color 150ms ease',
1891
1903
  };
1892
1904
  const sizeStyles = (preset) => {
@@ -1957,7 +1969,75 @@ const variantStyles = (preset) => {
1957
1969
  }
1958
1970
  };
1959
1971
  /**
1960
- * The preset's contribution to the button's inline style.
1972
+ * Per-instance colour slots the library stylesheet reads. Tone tokens stay
1973
+ * in the `var(--rulecms-button-brand, fallback)` form so a host `:root`
1974
+ * rebrand still wins.
1975
+ */
1976
+ const variantCssVariables = (preset) => {
1977
+ const palette = TONE_PALETTES[preset.tone];
1978
+ const tone = preset.tone;
1979
+ const ink = toneColor(tone, '', palette.base);
1980
+ const inkHover = toneColor(tone, 'hover', palette.hover);
1981
+ const contrast = toneColor(tone, 'contrast', palette.contrast);
1982
+ switch (preset.variant) {
1983
+ case 'solid':
1984
+ return asVars({
1985
+ [BUTTON_FILL_VARIABLE]: toneColor(tone, '', palette.base),
1986
+ [BUTTON_FILL_HOVER_VARIABLE]: toneColor(tone, 'hover', palette.hover),
1987
+ [BUTTON_FILL_ACTIVE_VARIABLE]: toneColor(tone, 'active', palette.active),
1988
+ [BUTTON_INK_VARIABLE]: contrast,
1989
+ [BUTTON_INK_HOVER_VARIABLE]: contrast,
1990
+ [BUTTON_BORDER_VARIABLE]: toneColor(tone, '', palette.base),
1991
+ [BUTTON_RING_VARIABLE]: ink,
1992
+ });
1993
+ case 'soft':
1994
+ return asVars({
1995
+ [BUTTON_FILL_VARIABLE]: toneColor(tone, 'soft', palette.soft),
1996
+ [BUTTON_FILL_HOVER_VARIABLE]: toneColor(tone, 'soft-hover', palette.softHover),
1997
+ [BUTTON_FILL_ACTIVE_VARIABLE]: `color-mix(in srgb, ${toneColor(tone, 'soft-hover', palette.softHover)} 88%, black)`,
1998
+ [BUTTON_INK_VARIABLE]: toneColor(tone, 'soft-contrast', palette.softContrast),
1999
+ [BUTTON_INK_HOVER_VARIABLE]: toneColor(tone, 'soft-contrast', palette.softContrast),
2000
+ [BUTTON_BORDER_VARIABLE]: 'transparent',
2001
+ [BUTTON_RING_VARIABLE]: ink,
2002
+ });
2003
+ case 'outline':
2004
+ return asVars({
2005
+ [BUTTON_FILL_VARIABLE]: 'transparent',
2006
+ [BUTTON_FILL_HOVER_VARIABLE]: toneColor(tone, 'soft', palette.soft),
2007
+ [BUTTON_FILL_ACTIVE_VARIABLE]: toneColor(tone, 'soft-hover', palette.softHover),
2008
+ [BUTTON_INK_VARIABLE]: ink,
2009
+ [BUTTON_INK_HOVER_VARIABLE]: inkHover,
2010
+ [BUTTON_BORDER_VARIABLE]: toneColor(tone, 'border', palette.border),
2011
+ [BUTTON_RING_VARIABLE]: ink,
2012
+ });
2013
+ case 'ghost':
2014
+ return asVars({
2015
+ [BUTTON_FILL_VARIABLE]: 'transparent',
2016
+ [BUTTON_FILL_HOVER_VARIABLE]: toneColor(tone, 'soft', palette.soft),
2017
+ [BUTTON_FILL_ACTIVE_VARIABLE]: toneColor(tone, 'soft-hover', palette.softHover),
2018
+ [BUTTON_INK_VARIABLE]: ink,
2019
+ [BUTTON_INK_HOVER_VARIABLE]: inkHover,
2020
+ [BUTTON_BORDER_VARIABLE]: 'transparent',
2021
+ [BUTTON_RING_VARIABLE]: ink,
2022
+ });
2023
+ case 'link':
2024
+ default:
2025
+ return asVars({
2026
+ [BUTTON_FILL_VARIABLE]: 'transparent',
2027
+ [BUTTON_FILL_HOVER_VARIABLE]: 'transparent',
2028
+ [BUTTON_FILL_ACTIVE_VARIABLE]: 'transparent',
2029
+ [BUTTON_INK_VARIABLE]: ink,
2030
+ [BUTTON_INK_HOVER_VARIABLE]: inkHover,
2031
+ [BUTTON_BORDER_VARIABLE]: 'transparent',
2032
+ [BUTTON_RING_VARIABLE]: ink,
2033
+ });
2034
+ }
2035
+ };
2036
+ const COLOR_STYLE_KEYS = ['backgroundColor', 'color', 'borderColor'];
2037
+ /**
2038
+ * The preset's contribution to the button's inline style, including resting
2039
+ * colours as real CSS properties. The composer picker uses this so a swatch
2040
+ * looks right without the library stylesheet.
1961
2041
  *
1962
2042
  * Callers spread column `styleProps` *after* this, which is what makes the
1963
2043
  * preset a set of defaults rather than a set of rules: anything the author
@@ -1968,6 +2048,41 @@ function buildButtonPresetStyles(preset) {
1968
2048
  ...structuralStyles,
1969
2049
  ...sizeStyles(preset),
1970
2050
  ...variantStyles(preset),
2051
+ ...variantCssVariables(preset),
2052
+ };
2053
+ }
2054
+ /**
2055
+ * What `RButton` puts on the element. Same as the picker styles, minus the
2056
+ * colour properties the library stylesheet owns — those stay on the element
2057
+ * only as custom properties so `:hover` can change them.
2058
+ */
2059
+ function buildButtonRenderStyles(preset) {
2060
+ const styles = { ...buildButtonPresetStyles(preset) };
2061
+ for (const key of COLOR_STYLE_KEYS) {
2062
+ delete styles[key];
2063
+ }
2064
+ return styles;
2065
+ }
2066
+ /**
2067
+ * Column styles still win on everything except `backgroundColor`, which is
2068
+ * remapped onto the fill slots so hover/active follow the authored colour
2069
+ * instead of the preset's blue-family hover.
2070
+ */
2071
+ function applyButtonColumnStyles(styleProps) {
2072
+ if (!styleProps) {
2073
+ return {};
2074
+ }
2075
+ const { backgroundColor, ...rest } = styleProps;
2076
+ if (backgroundColor === undefined || backgroundColor === '') {
2077
+ return rest;
2078
+ }
2079
+ return {
2080
+ ...rest,
2081
+ ...asVars({
2082
+ [BUTTON_FILL_VARIABLE]: backgroundColor,
2083
+ [BUTTON_FILL_HOVER_VARIABLE]: `color-mix(in srgb, ${backgroundColor} 82%, black)`,
2084
+ [BUTTON_FILL_ACTIVE_VARIABLE]: `color-mix(in srgb, ${backgroundColor} 70%, black)`,
2085
+ }),
1971
2086
  };
1972
2087
  }
1973
2088
  /** Applied on top when the button is disabled, before column styles. */
@@ -2099,9 +2214,9 @@ class RButtonComponent {
2099
2214
  }
2100
2215
  get style() {
2101
2216
  return {
2102
- ...buildButtonPresetStyles(this.preset),
2217
+ ...buildButtonRenderStyles(this.preset),
2103
2218
  ...(this.disabled ? disabledStyles : {}),
2104
- ...this.styleProps,
2219
+ ...applyButtonColumnStyles(this.styleProps),
2105
2220
  };
2106
2221
  }
2107
2222
  get label() {
@@ -2129,7 +2244,16 @@ class RButtonComponent {
2129
2244
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: RButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2130
2245
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.25", type: RButtonComponent, isStandalone: true, selector: "rulecms-r-button", inputs: { componentAttributes: "componentAttributes", styleProps: "styleProps", className: "className", widgetInstanceProps: "widgetInstanceProps" }, host: { styleAttribute: "display: contents" }, ngImport: i0, template: `
2131
2246
  @if (link && disabled) {
2132
- <a [ngStyle]="style" [class]="className || undefined" role="link" aria-disabled="true" [attr.aria-label]="ariaLabel">
2247
+ <a
2248
+ data-rulecms-button
2249
+ [attr.data-rulecms-button-variant]="preset.variant"
2250
+ [attr.data-rulecms-button-tone]="preset.tone"
2251
+ [ngStyle]="style"
2252
+ [class]="className || undefined"
2253
+ role="link"
2254
+ aria-disabled="true"
2255
+ [attr.aria-label]="ariaLabel"
2256
+ >
2133
2257
  @if (iconNode && iconPosition !== 'trailing') {
2134
2258
  <rulecms-svg-icon [iconNode]="iconNode" width="1em" height="1em" [styleProps]="{ flexShrink: 0 }" />
2135
2259
  }
@@ -2140,6 +2264,9 @@ class RButtonComponent {
2140
2264
  </a>
2141
2265
  } @else if (link) {
2142
2266
  <a
2267
+ data-rulecms-button
2268
+ [attr.data-rulecms-button-variant]="preset.variant"
2269
+ [attr.data-rulecms-button-tone]="preset.tone"
2143
2270
  [attr.href]="link.href"
2144
2271
  [attr.target]="link.target"
2145
2272
  [attr.rel]="link.rel"
@@ -2163,6 +2290,9 @@ class RButtonComponent {
2163
2290
  } @else {
2164
2291
  <button
2165
2292
  type="button"
2293
+ data-rulecms-button
2294
+ [attr.data-rulecms-button-variant]="preset.variant"
2295
+ [attr.data-rulecms-button-tone]="preset.tone"
2166
2296
  [disabled]="disabled"
2167
2297
  [ngStyle]="style"
2168
2298
  [class]="className || undefined"
@@ -2188,7 +2318,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
2188
2318
  imports: [NgStyle, SvgIconComponent],
2189
2319
  template: `
2190
2320
  @if (link && disabled) {
2191
- <a [ngStyle]="style" [class]="className || undefined" role="link" aria-disabled="true" [attr.aria-label]="ariaLabel">
2321
+ <a
2322
+ data-rulecms-button
2323
+ [attr.data-rulecms-button-variant]="preset.variant"
2324
+ [attr.data-rulecms-button-tone]="preset.tone"
2325
+ [ngStyle]="style"
2326
+ [class]="className || undefined"
2327
+ role="link"
2328
+ aria-disabled="true"
2329
+ [attr.aria-label]="ariaLabel"
2330
+ >
2192
2331
  @if (iconNode && iconPosition !== 'trailing') {
2193
2332
  <rulecms-svg-icon [iconNode]="iconNode" width="1em" height="1em" [styleProps]="{ flexShrink: 0 }" />
2194
2333
  }
@@ -2199,6 +2338,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
2199
2338
  </a>
2200
2339
  } @else if (link) {
2201
2340
  <a
2341
+ data-rulecms-button
2342
+ [attr.data-rulecms-button-variant]="preset.variant"
2343
+ [attr.data-rulecms-button-tone]="preset.tone"
2202
2344
  [attr.href]="link.href"
2203
2345
  [attr.target]="link.target"
2204
2346
  [attr.rel]="link.rel"
@@ -2222,6 +2364,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
2222
2364
  } @else {
2223
2365
  <button
2224
2366
  type="button"
2367
+ data-rulecms-button
2368
+ [attr.data-rulecms-button-variant]="preset.variant"
2369
+ [attr.data-rulecms-button-tone]="preset.tone"
2225
2370
  [disabled]="disabled"
2226
2371
  [ngStyle]="style"
2227
2372
  [class]="className || undefined"
@@ -2256,13 +2401,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
2256
2401
  * nothing, and would put the column's background behind the button rather than
2257
2402
  * on it. No configuration changes that.
2258
2403
  */
2259
- const resolveNoContainer$4 = () => false;
2404
+ const resolveNoContainer$5 = () => false;
2260
2405
 
2261
2406
  /**
2262
2407
  * There is always a root element to carry the class: the button is the
2263
2408
  * component, so no configuration leaves it without one.
2264
2409
  */
2265
- const resolveRendersOwnElement$4 = () => true;
2410
+ const resolveRendersOwnElement$5 = () => true;
2266
2411
 
2267
2412
  /**
2268
2413
  * Seeds the button's own semantics only.
@@ -2275,7 +2420,7 @@ const resolveRendersOwnElement$4 = () => true;
2275
2420
  * happened to cover. Leaving the bag empty is what lets "unset means preset"
2276
2421
  * be true.
2277
2422
  */
2278
- const defaultAttributeValues$4 = [
2423
+ const defaultAttributeValues$5 = [
2279
2424
  {
2280
2425
  name: BUTTON_PRESET_ATTRIBUTE,
2281
2426
  defaultValues: {
@@ -2299,7 +2444,7 @@ const defaultAttributeValues$4 = [
2299
2444
  * documentation registry asserts its pages match that sequence, so moving an
2300
2445
  * entry here moves it in both places at once.
2301
2446
  */
2302
- const attributeEditModeConfigs$4 = [
2447
+ const attributeEditModeConfigs$5 = [
2303
2448
  {
2304
2449
  name: BUTTON_PRESET_ATTRIBUTE,
2305
2450
  heading: 'Button Style',
@@ -2338,13 +2483,13 @@ const attributeEditModeConfigs$4 = [
2338
2483
  },
2339
2484
  ];
2340
2485
 
2341
- const displayCardEntry$4 = {
2486
+ const displayCardEntry$5 = {
2342
2487
  id: ComponentIdentifiers.rButton,
2343
- resolveNoContainer: resolveNoContainer$4,
2344
- resolveRendersOwnElement: resolveRendersOwnElement$4,
2488
+ resolveNoContainer: resolveNoContainer$5,
2489
+ resolveRendersOwnElement: resolveRendersOwnElement$5,
2345
2490
  card: RButtonComponent,
2346
- defaultAttributeValues: defaultAttributeValues$4,
2347
- attributeEditModeConfigs: attributeEditModeConfigs$4,
2491
+ defaultAttributeValues: defaultAttributeValues$5,
2492
+ attributeEditModeConfigs: attributeEditModeConfigs$5,
2348
2493
  };
2349
2494
 
2350
2495
  /**
@@ -2474,13 +2619,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
2474
2619
  * width and border on itself, so a wrapper div would only add a redundant
2475
2620
  * element. No configuration changes that.
2476
2621
  */
2477
- const resolveNoContainer$3 = () => false;
2622
+ const resolveNoContainer$4 = () => false;
2478
2623
 
2479
2624
  /**
2480
2625
  * The `<hr>` carries the className. There is always exactly one element and it
2481
2626
  * is always the root, so there is nothing for this to depend on.
2482
2627
  */
2483
- const resolveRendersOwnElement$3 = () => true;
2628
+ const resolveRendersOwnElement$4 = () => true;
2484
2629
 
2485
2630
  /**
2486
2631
  * Seeds the divider's own two settings so the drawer opens on the values a
@@ -2490,7 +2635,7 @@ const resolveRendersOwnElement$3 = () => true;
2490
2635
  * names are the divider's own, so nothing in Column Styles writes to them and
2491
2636
  * a seeded value can never shadow a style the author set.
2492
2637
  */
2493
- const defaultAttributeValues$3 = [
2638
+ const defaultAttributeValues$4 = [
2494
2639
  {
2495
2640
  name: DIVIDER_STYLE_ATTRIBUTE,
2496
2641
  defaultValues: {
@@ -2512,7 +2657,7 @@ const defaultAttributeValues$3 = [
2512
2657
  * documentation registry asserts its pages match that sequence, so moving an
2513
2658
  * entry here moves it in both places at once.
2514
2659
  */
2515
- const attributeEditModeConfigs$3 = [
2660
+ const attributeEditModeConfigs$4 = [
2516
2661
  {
2517
2662
  name: DIVIDER_STYLE_ATTRIBUTE,
2518
2663
  heading: 'Line Style',
@@ -2527,13 +2672,13 @@ const attributeEditModeConfigs$3 = [
2527
2672
  },
2528
2673
  ];
2529
2674
 
2530
- const displayCardEntry$3 = {
2675
+ const displayCardEntry$4 = {
2531
2676
  id: ComponentIdentifiers.rDivider,
2532
- resolveNoContainer: resolveNoContainer$3,
2533
- resolveRendersOwnElement: resolveRendersOwnElement$3,
2677
+ resolveNoContainer: resolveNoContainer$4,
2678
+ resolveRendersOwnElement: resolveRendersOwnElement$4,
2534
2679
  card: RDividerComponent,
2535
- defaultAttributeValues: defaultAttributeValues$3,
2536
- attributeEditModeConfigs: attributeEditModeConfigs$3,
2680
+ defaultAttributeValues: defaultAttributeValues$4,
2681
+ attributeEditModeConfigs: attributeEditModeConfigs$4,
2537
2682
  };
2538
2683
 
2539
2684
  /**
@@ -2971,7 +3116,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
2971
3116
  * Deciding this from `resolveEmbed`, rather than from the fact that this
2972
3117
  * component "is an iframe component", is what keeps the two in step.
2973
3118
  */
2974
- const resolveNoContainer$2 = ({ componentAttributes }) => resolveEmbed(componentAttributes) === null;
3119
+ const resolveNoContainer$3 = ({ componentAttributes }) => resolveEmbed(componentAttributes) === null;
2975
3120
 
2976
3121
  /**
2977
3122
  * The iframe carries the className — when there is one. A rejected or unset
@@ -2979,7 +3124,7 @@ const resolveNoContainer$2 = ({ componentAttributes }) => resolveEmbed(component
2979
3124
  * disappears without trace, so this answers from the same resolution the
2980
3125
  * component uses.
2981
3126
  */
2982
- const resolveRendersOwnElement$2 = ({ componentAttributes, }) => resolveEmbed(componentAttributes) !== null;
3127
+ const resolveRendersOwnElement$3 = ({ componentAttributes, }) => resolveEmbed(componentAttributes) !== null;
2983
3128
 
2984
3129
  /**
2985
3130
  * Nothing is seeded, including the URL.
@@ -2992,7 +3137,7 @@ const resolveRendersOwnElement$2 = ({ componentAttributes, }) => resolveEmbed(co
2992
3137
  * Aspect ratio is left unset on purpose too, so it resolves from the provider
2993
3138
  * — a map is 4:3 and a video is 16:9 without either being written down here.
2994
3139
  */
2995
- const defaultAttributeValues$2 = [
3140
+ const defaultAttributeValues$3 = [
2996
3141
  {
2997
3142
  name: 'embed-url-3-resolutions',
2998
3143
  defaultValues: {},
@@ -3016,7 +3161,7 @@ const defaultAttributeValues$2 = [
3016
3161
  * the URL first because nothing renders without it, then the three settings
3017
3162
  * that only matter once something does.
3018
3163
  */
3019
- const attributeEditModeConfigs$2 = [
3164
+ const attributeEditModeConfigs$3 = [
3020
3165
  {
3021
3166
  name: 'embed-url-3-resolutions',
3022
3167
  heading: 'Embed URL',
@@ -3043,13 +3188,13 @@ const attributeEditModeConfigs$2 = [
3043
3188
  },
3044
3189
  ];
3045
3190
 
3046
- const displayCardEntry$2 = {
3191
+ const displayCardEntry$3 = {
3047
3192
  id: ComponentIdentifiers.rEmbed,
3048
- resolveNoContainer: resolveNoContainer$2,
3049
- resolveRendersOwnElement: resolveRendersOwnElement$2,
3193
+ resolveNoContainer: resolveNoContainer$3,
3194
+ resolveRendersOwnElement: resolveRendersOwnElement$3,
3050
3195
  card: REmbedComponent,
3051
- defaultAttributeValues: defaultAttributeValues$2,
3052
- attributeEditModeConfigs: attributeEditModeConfigs$2,
3196
+ defaultAttributeValues: defaultAttributeValues$3,
3197
+ attributeEditModeConfigs: attributeEditModeConfigs$3,
3053
3198
  };
3054
3199
 
3055
3200
  /**
@@ -3250,16 +3395,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
3250
3395
  * that element itself. No configuration changes the answer, so no wrapper
3251
3396
  * div, ever.
3252
3397
  */
3253
- const resolveNoContainer$1 = () => false;
3398
+ const resolveNoContainer$2 = () => false;
3254
3399
 
3255
3400
  /**
3256
3401
  * RList's root is always a real element — `<ul>` or `<ol>` — so it can always
3257
3402
  * carry the column's className, and the component applies the one it
3258
3403
  * receives.
3259
3404
  */
3260
- const resolveRendersOwnElement$1 = () => true;
3405
+ const resolveRendersOwnElement$2 = () => true;
3261
3406
 
3262
- const defaultAttributeValues$1 = [
3407
+ const defaultAttributeValues$2 = [
3263
3408
  {
3264
3409
  name: LIST_ITEMS_ATTRIBUTE,
3265
3410
  defaultValues: {
@@ -3300,7 +3445,7 @@ const defaultAttributeValues$1 = [
3300
3445
  * documentation registry asserts its pages match that sequence, so moving an
3301
3446
  * entry here moves it in both places at once.
3302
3447
  */
3303
- const attributeEditModeConfigs$1 = [
3448
+ const attributeEditModeConfigs$2 = [
3304
3449
  {
3305
3450
  name: LIST_ITEMS_ATTRIBUTE,
3306
3451
  heading: 'List Items',
@@ -3339,13 +3484,13 @@ const attributeEditModeConfigs$1 = [
3339
3484
  },
3340
3485
  ];
3341
3486
 
3342
- const displayCardEntry$1 = {
3487
+ const displayCardEntry$2 = {
3343
3488
  id: ComponentIdentifiers.rList,
3344
- resolveNoContainer: resolveNoContainer$1,
3345
- resolveRendersOwnElement: resolveRendersOwnElement$1,
3489
+ resolveNoContainer: resolveNoContainer$2,
3490
+ resolveRendersOwnElement: resolveRendersOwnElement$2,
3346
3491
  card: RListComponent,
3347
- defaultAttributeValues: defaultAttributeValues$1,
3348
- attributeEditModeConfigs: attributeEditModeConfigs$1,
3492
+ defaultAttributeValues: defaultAttributeValues$2,
3493
+ attributeEditModeConfigs: attributeEditModeConfigs$2,
3349
3494
  };
3350
3495
 
3351
3496
  /**
@@ -3578,15 +3723,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImpo
3578
3723
  * element itself. No configuration changes the answer, so no wrapper div,
3579
3724
  * ever.
3580
3725
  */
3581
- const resolveNoContainer = () => false;
3726
+ const resolveNoContainer$1 = () => false;
3582
3727
 
3583
3728
  /**
3584
3729
  * RAccordion's root is always a real element — `<details>` — so it can always
3585
3730
  * carry the column's className, and the component applies the one it receives.
3586
3731
  */
3587
- const resolveRendersOwnElement = () => true;
3732
+ const resolveRendersOwnElement$1 = () => true;
3588
3733
 
3589
- const defaultAttributeValues = [
3734
+ const defaultAttributeValues$1 = [
3590
3735
  {
3591
3736
  name: ACCORDION_SUMMARY_ATTRIBUTE,
3592
3737
  defaultValues: {
@@ -3631,7 +3776,7 @@ const defaultAttributeValues = [
3631
3776
  * documentation registry asserts its pages match that sequence, so moving an
3632
3777
  * entry here moves it in both places at once.
3633
3778
  */
3634
- const attributeEditModeConfigs = [
3779
+ const attributeEditModeConfigs$1 = [
3635
3780
  {
3636
3781
  name: ACCORDION_SUMMARY_ATTRIBUTE,
3637
3782
  heading: 'Summary',
@@ -3664,16 +3809,280 @@ const attributeEditModeConfigs = [
3664
3809
  },
3665
3810
  ];
3666
3811
 
3667
- const displayCardEntry = {
3812
+ const displayCardEntry$1 = {
3668
3813
  id: ComponentIdentifiers.rAccordion,
3814
+ resolveNoContainer: resolveNoContainer$1,
3815
+ resolveRendersOwnElement: resolveRendersOwnElement$1,
3816
+ card: RAccordionComponent,
3817
+ defaultAttributeValues: defaultAttributeValues$1,
3818
+ attributeEditModeConfigs: attributeEditModeConfigs$1,
3819
+ };
3820
+
3821
+ /**
3822
+ * The attribute names `r-mount` reads.
3823
+ *
3824
+ * Two, and that is the whole of it: which host component to render, and the
3825
+ * props the author filled in for it. The host application supplies the actual
3826
+ * Angular component through `rulecms-widget`'s `mounts` map. This library never
3827
+ * imports customer code.
3828
+ */
3829
+ const MOUNT_NAME_ATTRIBUTE = 'mount-name-3-resolutions';
3830
+ const MOUNT_PROPS_ATTRIBUTE = 'mount-props-3-resolutions';
3831
+ const MOUNT_PROP_TYPES = ['string', 'number', 'boolean', 'json'];
3832
+ const MOUNT_NAME_PATTERN = /^[a-zA-Z][a-zA-Z0-9_-]{0,63}$/;
3833
+ const FORBIDDEN_PROP_KEYS = new Set([
3834
+ '__proto__',
3835
+ 'constructor',
3836
+ 'prototype',
3837
+ 'key',
3838
+ 'ref',
3839
+ 'children',
3840
+ 'dangerouslySetInnerHTML',
3841
+ ]);
3842
+ const HTML_EVENT_KEYS = new Set([
3843
+ 'onclick',
3844
+ 'onsubmit',
3845
+ 'onload',
3846
+ 'onerror',
3847
+ 'onmouseover',
3848
+ 'onmouseenter',
3849
+ 'onfocus',
3850
+ 'onblur',
3851
+ 'onchange',
3852
+ 'oninput',
3853
+ 'onkeydown',
3854
+ 'onkeyup',
3855
+ ]);
3856
+ const isMountPropType = (value) => typeof value === 'string' && MOUNT_PROP_TYPES.includes(value);
3857
+ const isAllowedMountName = (value) => typeof value === 'string' && MOUNT_NAME_PATTERN.test(value);
3858
+ const isForbiddenMountPropKey = (key) => {
3859
+ if (FORBIDDEN_PROP_KEYS.has(key) || HTML_EVENT_KEYS.has(key.toLowerCase())) {
3860
+ return true;
3861
+ }
3862
+ return /^on[A-Z]/.test(key);
3863
+ };
3864
+ const resolveMountName = (componentAttributes) => {
3865
+ const value = componentAttributes?.[MOUNT_NAME_ATTRIBUTE];
3866
+ return isAllowedMountName(value) ? value : '';
3867
+ };
3868
+ const isMountPropRow = (value) => {
3869
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
3870
+ return false;
3871
+ }
3872
+ const row = value;
3873
+ return (typeof row.key === 'string' &&
3874
+ isMountPropType(row.type) &&
3875
+ typeof row.value === 'string');
3876
+ };
3877
+ const coerceMountPropValue = (row) => {
3878
+ switch (row.type) {
3879
+ case 'string':
3880
+ return row.value;
3881
+ case 'number': {
3882
+ const parsed = Number(row.value);
3883
+ return Number.isFinite(parsed) ? parsed : undefined;
3884
+ }
3885
+ case 'boolean':
3886
+ if (row.value === 'true') {
3887
+ return true;
3888
+ }
3889
+ if (row.value === 'false') {
3890
+ return false;
3891
+ }
3892
+ return undefined;
3893
+ case 'json':
3894
+ try {
3895
+ return JSON.parse(row.value);
3896
+ }
3897
+ catch {
3898
+ return undefined;
3899
+ }
3900
+ default:
3901
+ return undefined;
3902
+ }
3903
+ };
3904
+ const resolveMountProps = (componentAttributes) => {
3905
+ const raw = componentAttributes?.[MOUNT_PROPS_ATTRIBUTE];
3906
+ if (!Array.isArray(raw)) {
3907
+ return {};
3908
+ }
3909
+ const props = {};
3910
+ for (const entry of raw) {
3911
+ if (!isMountPropRow(entry)) {
3912
+ continue;
3913
+ }
3914
+ const key = entry.key.trim();
3915
+ if (!key || isForbiddenMountPropKey(key)) {
3916
+ continue;
3917
+ }
3918
+ const coerced = coerceMountPropValue(entry);
3919
+ if (coerced === undefined) {
3920
+ continue;
3921
+ }
3922
+ props[key] = coerced;
3923
+ }
3924
+ return props;
3925
+ };
3926
+
3927
+ const PLACEHOLDER_STYLE = {
3928
+ boxSizing: 'border-box',
3929
+ border: '1px dashed #94a3b8',
3930
+ borderRadius: 4,
3931
+ padding: '12px 16px',
3932
+ color: '#64748b',
3933
+ fontSize: 13,
3934
+ lineHeight: 1.4,
3935
+ fontFamily: 'system-ui, sans-serif',
3936
+ backgroundColor: '#f8fafc',
3937
+ };
3938
+ const resolveMountRender = ({ componentAttributes, mounts, widgetInstanceProps, styleProps, }) => {
3939
+ const name = resolveMountName(componentAttributes);
3940
+ const hostComponent = name && mounts ? mounts[name] : undefined;
3941
+ return {
3942
+ name,
3943
+ hostComponent,
3944
+ placeholderLabel: name || 'Custom Component',
3945
+ rootStyle: hostComponent ? styleProps : { ...PLACEHOLDER_STYLE, ...styleProps },
3946
+ hostInputs: {
3947
+ ...widgetInstanceProps,
3948
+ ...resolveMountProps(componentAttributes),
3949
+ },
3950
+ shouldWarn: Boolean(name && mounts && !hostComponent),
3951
+ };
3952
+ };
3953
+ const warnUnmatchedMount = (name, registered) => {
3954
+ const nodeEnv = globalThis.process?.env
3955
+ ?.NODE_ENV;
3956
+ if (nodeEnv === 'production') {
3957
+ return;
3958
+ }
3959
+ const available = registered.length ? registered.join(', ') : '(none)';
3960
+ console.warn(`r-mount: no host component registered as "${name}". Registered names: ${available}.`);
3961
+ };
3962
+
3963
+ /**
3964
+ * A leaf that renders a host-app component by name.
3965
+ *
3966
+ * The author sets a name and a list of typed props in the composer. The host
3967
+ * application passes the actual component on `rulecms-widget`'s `mounts` map.
3968
+ * This file never imports customer code: a miss is a placeholder, not a
3969
+ * lookup into executable text.
3970
+ *
3971
+ * The root is always a `<div>`. Author props are never spread onto this div
3972
+ * — only onto the resolved host component via `NgComponentOutlet`.
3973
+ */
3974
+ class RMountComponent {
3975
+ constructor() {
3976
+ this.state = resolveMountRender({});
3977
+ }
3978
+ ngOnChanges() {
3979
+ this.state = resolveMountRender({
3980
+ componentAttributes: this.componentAttributes,
3981
+ mounts: this.mounts,
3982
+ widgetInstanceProps: this.widgetInstanceProps,
3983
+ styleProps: this.styleProps,
3984
+ });
3985
+ if (this.state.shouldWarn && this.mounts) {
3986
+ warnUnmatchedMount(this.state.name, Object.keys(this.mounts));
3987
+ }
3988
+ }
3989
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: RMountComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3990
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.25", type: RMountComponent, isStandalone: true, selector: "rulecms-r-mount", inputs: { componentAttributes: "componentAttributes", styleProps: "styleProps", className: "className", mounts: "mounts", widgetInstanceProps: "widgetInstanceProps" }, usesOnChanges: true, ngImport: i0, template: `
3991
+ <div [ngStyle]="state.rootStyle" [class]="className || undefined">
3992
+ @if (state.hostComponent) {
3993
+ <ng-container *ngComponentOutlet="state.hostComponent; inputs: state.hostInputs" />
3994
+ } @else {
3995
+ {{ state.placeholderLabel }}
3996
+ }
3997
+ </div>
3998
+ `, isInline: true, dependencies: [{ kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"], exportAs: ["ngComponentOutlet"] }] }); }
3999
+ }
4000
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.25", ngImport: i0, type: RMountComponent, decorators: [{
4001
+ type: Component,
4002
+ args: [{
4003
+ selector: 'rulecms-r-mount',
4004
+ standalone: true,
4005
+ imports: [NgStyle, NgComponentOutlet],
4006
+ template: `
4007
+ <div [ngStyle]="state.rootStyle" [class]="className || undefined">
4008
+ @if (state.hostComponent) {
4009
+ <ng-container *ngComponentOutlet="state.hostComponent; inputs: state.hostInputs" />
4010
+ } @else {
4011
+ {{ state.placeholderLabel }}
4012
+ }
4013
+ </div>
4014
+ `,
4015
+ }]
4016
+ }], propDecorators: { componentAttributes: [{
4017
+ type: Input
4018
+ }], styleProps: [{
4019
+ type: Input
4020
+ }], className: [{
4021
+ type: Input
4022
+ }], mounts: [{
4023
+ type: Input
4024
+ }], widgetInstanceProps: [{
4025
+ type: Input
4026
+ }] } });
4027
+
4028
+ /**
4029
+ * Always renders a root `<div>` that holds the column's box styles — either
4030
+ * around the host component or around the placeholder. The host component is
4031
+ * unknown to this library, so it cannot be trusted to carry styles itself.
4032
+ */
4033
+ const resolveNoContainer = () => false;
4034
+
4035
+ /**
4036
+ * The root `<div>` carries the className. There is always exactly one element
4037
+ * and it is always the root, whether the host component resolved or not.
4038
+ */
4039
+ const resolveRendersOwnElement = () => true;
4040
+
4041
+ /**
4042
+ * A fresh mount has no name and no props. Seeding either would invent a
4043
+ * registration the host does not have, so both stay empty until the author
4044
+ * fills them in.
4045
+ */
4046
+ const defaultAttributeValues = [
4047
+ {
4048
+ name: MOUNT_NAME_ATTRIBUTE,
4049
+ defaultValues: {},
4050
+ },
4051
+ {
4052
+ name: MOUNT_PROPS_ATTRIBUTE,
4053
+ defaultValues: {},
4054
+ },
4055
+ ];
4056
+
4057
+ /**
4058
+ * Both settings the mount offers, in the order the Modify drawer shows them.
4059
+ */
4060
+ const attributeEditModeConfigs = [
4061
+ {
4062
+ name: MOUNT_NAME_ATTRIBUTE,
4063
+ heading: 'Component Name',
4064
+ subHeading: 'The name your developer registered in the app. Must match exactly, for 3 different device resolutions',
4065
+ defaultValues: {},
4066
+ },
4067
+ {
4068
+ name: MOUNT_PROPS_ATTRIBUTE,
4069
+ heading: 'Props',
4070
+ subHeading: 'Name and value pairs passed to that component. The component decides what each name means, for 3 different device resolutions',
4071
+ defaultValues: {},
4072
+ },
4073
+ ];
4074
+
4075
+ const displayCardEntry = {
4076
+ id: ComponentIdentifiers.rMount,
3669
4077
  resolveNoContainer,
3670
4078
  resolveRendersOwnElement,
3671
- card: RAccordionComponent,
4079
+ card: RMountComponent,
3672
4080
  defaultAttributeValues,
3673
4081
  attributeEditModeConfigs,
3674
4082
  };
3675
4083
 
3676
4084
  const cardEntries$1 = [
4085
+ displayCardEntry$9,
3677
4086
  displayCardEntry$8,
3678
4087
  displayCardEntry$7,
3679
4088
  displayCardEntry$6,
@@ -3782,6 +4191,11 @@ const componentNameToModifyAttribute = {
3782
4191
  'accordion-open-3-resolutions': 'accordion-open-3-resolutions',
3783
4192
  'accordion-heading-level-3-resolutions': 'accordion-heading-level-3-resolutions',
3784
4193
  'accordion-links-3-resolutions': 'links-3-resolutions',
4194
+ // r-mount: the name is a constrained identifier and reuses the shared
4195
+ // plain-text editor; the props list is a repeatable key/type/value row
4196
+ // and needs its own editor.
4197
+ 'mount-name-3-resolutions': 'image-text-3-resolutions',
4198
+ 'mount-props-3-resolutions': 'mount-props-3-resolutions',
3785
4199
  'content-title-3-resolutions': 'content-title-3-resolutions',
3786
4200
  'media-selector-3-resolutions': 'media-selector-3-resolutions',
3787
4201
  'pass-through-image-attributes-alt-3-resolutions': 'image-alt-text-3-resolutions',
@@ -3855,6 +4269,7 @@ const cardEntries = [
3855
4269
  { id: ComponentIdentifiers.rEmbed, icon: '⧉', label: 'Embed' },
3856
4270
  { id: ComponentIdentifiers.rList, icon: '☰', label: 'List' },
3857
4271
  { id: ComponentIdentifiers.rAccordion, icon: '▸', label: 'Accordion' },
4272
+ { id: ComponentIdentifiers.rMount, icon: '⌘', label: 'Custom' },
3858
4273
  ];
3859
4274
 
3860
4275
  const cardGroups = [
@@ -3896,6 +4311,49 @@ const getPreviewComponents = () => {
3896
4311
  return cachedPreviewComponents;
3897
4312
  };
3898
4313
 
4314
+ /**
4315
+ * SSR-safe rules for `r-button` pseudo-classes.
4316
+ *
4317
+ * widget-angular injects this once per library via `ComponentLibraryModule.stylesheet`.
4318
+ * The sheet owns `background-color`, `color`, and `border-color` so `:hover`
4319
+ * can win — those properties on an inline style beat any stylesheet rule.
4320
+ * Resting values arrive as `--rulecms-button-fill` / `-ink` / `-border` on
4321
+ * the element. A column background override rewrites the fill slots and
4322
+ * derives hover/active with `color-mix`, so an arbitrary red does not keep
4323
+ * the brand-blue hover.
4324
+ *
4325
+ * Outline is never cleared: the designed ring is a `box-shadow` on
4326
+ * `:focus-visible`, on top of the browser's native focus outline.
4327
+ */
4328
+ const BUTTON_LIBRARY_STYLESHEET = `
4329
+ [data-rulecms-button] {
4330
+ background-color: var(--rulecms-button-fill);
4331
+ color: var(--rulecms-button-ink);
4332
+ border-color: var(--rulecms-button-border, var(--rulecms-button-fill));
4333
+ }
4334
+ [data-rulecms-button]:hover:not(:disabled):not([aria-disabled="true"]) {
4335
+ background-color: var(--rulecms-button-fill-hover);
4336
+ color: var(--rulecms-button-ink-hover, var(--rulecms-button-ink));
4337
+ border-color: var(--rulecms-button-fill-hover);
4338
+ }
4339
+ [data-rulecms-button]:active:not(:disabled):not([aria-disabled="true"]) {
4340
+ background-color: var(--rulecms-button-fill-active);
4341
+ border-color: var(--rulecms-button-fill-active);
4342
+ }
4343
+ [data-rulecms-button][data-rulecms-button-variant="outline"]:hover:not(:disabled):not([aria-disabled="true"]),
4344
+ [data-rulecms-button][data-rulecms-button-variant="ghost"]:hover:not(:disabled):not([aria-disabled="true"]) {
4345
+ border-color: var(--rulecms-button-border, var(--rulecms-button-ink));
4346
+ }
4347
+ [data-rulecms-button][data-rulecms-button-variant="link"]:hover:not(:disabled):not([aria-disabled="true"]),
4348
+ [data-rulecms-button][data-rulecms-button-variant="link"]:active:not(:disabled):not([aria-disabled="true"]) {
4349
+ background-color: transparent;
4350
+ border-color: transparent;
4351
+ }
4352
+ [data-rulecms-button]:focus-visible {
4353
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--rulecms-button-ring, var(--rulecms-button-ink)) 40%, transparent);
4354
+ }
4355
+ `.trim();
4356
+
3899
4357
  /**
3900
4358
  * ComponentLibraryModule conformance (the @rulecms/widget-angular contract).
3901
4359
  *
@@ -3909,11 +4367,17 @@ const getPreviewComponents = () => {
3909
4367
  */
3910
4368
  const manifest = {
3911
4369
  id: 'default',
3912
- version: '0.1.0',
4370
+ version: '0.2.0',
3913
4371
  angularPeerRange: '>=17.0.0',
3914
4372
  };
3915
4373
  /** The render surface: component type → renderable entry. */
3916
4374
  const components = getSourceComponentsPlugin().components;
4375
+ /**
4376
+ * Optional `ComponentLibraryModule.stylesheet`. widget-angular injects this
4377
+ * once per library as an SSR `<style>` tag. v1 is the button hover / focus /
4378
+ * active rules; later interactive cards append here.
4379
+ */
4380
+ const stylesheet = BUTTON_LIBRARY_STYLESHEET;
3917
4381
  /** The editor surface: palette + attribute metadata for the RuleCMS composer. */
3918
4382
  const editor = {
3919
4383
  previewComponents: getPreviewComponents(),
@@ -3975,5 +4439,5 @@ function serializeInlineMarkers(runs) {
3975
4439
  * Generated bundle index. Do not edit.
3976
4440
  */
3977
4441
 
3978
- export { ACCORDION_HEADING_LEVELS, BLOCK_ENCLOSING_TAGS, BUTTON_CLICK_HANDLER_PROP, BUTTON_CSS_VARIABLE_PREFIX, BUTTON_SIZES, BUTTON_TONES, BUTTON_VARIANTS, ComponentIdentifiers, DEFAULT_ACCORDION_HEADING_LEVEL, DEFAULT_BUTTON_LABEL, DEFAULT_BUTTON_PRESET, DEFAULT_EMBED_LOADING, DEFAULT_ICON_POSITION, DEFAULT_LIST_KIND, EMBED_ASPECT_RATIOS, EMBED_LOADING_VALUES, EMBED_PROVIDERS, EMBED_UNSHAPED_HEIGHT, ENCLOSING_TAGS, ICON_POSITIONS, INLINE_ENCLOSING_TAGS, InlineMarkupComponent, LIST_KINDS, LIST_MARKERS, REJECTED_HREF_SCHEMES, SIZE_SCALES, TONE_PALETTES, buildButtonPresetStyles, disabledStyles as buttonDisabledStyles, cardGroups$1 as cardGroups, components, editor, formatInlineMarker, getComponentMetadataForEditing, getPreviewCardGroups, getPreviewComponents, getSourceComponentsPlugin, isAllowedEmbedUrl, isBlockEnclosingTag, isButtonSize, isButtonTone, isButtonVariant, isEnclosingTag, isSafeHref, manifest, normaliseHost, parseInlineLinkMarkers, parseInlineMarkers, resolveButtonPreset, resolveEmbedUrl, resolveLinkAttributes, serializeInlineMarkers, toneCssVariable };
4442
+ export { ACCORDION_HEADING_LEVELS, BLOCK_ENCLOSING_TAGS, BUTTON_BORDER_VARIABLE, BUTTON_CLICK_HANDLER_PROP, BUTTON_CSS_VARIABLE_PREFIX, BUTTON_FILL_ACTIVE_VARIABLE, BUTTON_FILL_HOVER_VARIABLE, BUTTON_FILL_VARIABLE, BUTTON_INK_HOVER_VARIABLE, BUTTON_INK_VARIABLE, BUTTON_LIBRARY_STYLESHEET, BUTTON_RING_VARIABLE, BUTTON_SIZES, BUTTON_TONES, BUTTON_VARIANTS, ComponentIdentifiers, DEFAULT_ACCORDION_HEADING_LEVEL, DEFAULT_BUTTON_LABEL, DEFAULT_BUTTON_PRESET, DEFAULT_EMBED_LOADING, DEFAULT_ICON_POSITION, DEFAULT_LIST_KIND, EMBED_ASPECT_RATIOS, EMBED_LOADING_VALUES, EMBED_PROVIDERS, EMBED_UNSHAPED_HEIGHT, ENCLOSING_TAGS, ICON_POSITIONS, INLINE_ENCLOSING_TAGS, InlineMarkupComponent, LIST_KINDS, LIST_MARKERS, MOUNT_NAME_ATTRIBUTE, MOUNT_NAME_PATTERN, MOUNT_PROPS_ATTRIBUTE, MOUNT_PROP_TYPES, REJECTED_HREF_SCHEMES, SIZE_SCALES, TONE_PALETTES, applyButtonColumnStyles, buildButtonPresetStyles, buildButtonRenderStyles, disabledStyles as buttonDisabledStyles, cardGroups$1 as cardGroups, components, editor, formatInlineMarker, getComponentMetadataForEditing, getPreviewCardGroups, getPreviewComponents, getSourceComponentsPlugin, isAllowedEmbedUrl, isAllowedMountName, isBlockEnclosingTag, isButtonSize, isButtonTone, isButtonVariant, isEnclosingTag, isForbiddenMountPropKey, isSafeHref, manifest, normaliseHost, parseInlineLinkMarkers, parseInlineMarkers, resolveButtonPreset, resolveEmbedUrl, resolveLinkAttributes, resolveMountName, resolveMountProps, serializeInlineMarkers, stylesheet, toneCssVariable };
3979
4443
  //# sourceMappingURL=rulecms-source-components-angular.mjs.map