@oicl/openbridge-webcomponents-full-bundle 2.0.0-next.119 → 2.0.0-next.121

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 (51) hide show
  1. package/bundle/openbridge-webcomponents.bundle.js +118 -14
  2. package/bundle/openbridge-webcomponents.bundle.js.map +1 -1
  3. package/custom-elements.json +45 -1
  4. package/dist/components/alert-button/alert-button.d.ts +3 -0
  5. package/dist/components/alert-button/alert-button.d.ts.map +1 -1
  6. package/dist/components/alert-button/alert-button.js +12 -0
  7. package/dist/components/alert-button/alert-button.js.map +1 -1
  8. package/dist/components/alert-frame/alert-frame.css.js +1 -0
  9. package/dist/components/alert-frame/alert-frame.css.js.map +1 -1
  10. package/dist/components/alert-frame/alert-frame.d.ts +5 -0
  11. package/dist/components/alert-frame/alert-frame.d.ts.map +1 -1
  12. package/dist/components/alert-frame/alert-frame.js +24 -0
  13. package/dist/components/alert-frame/alert-frame.js.map +1 -1
  14. package/dist/components/alert-icon/alert-icon.d.ts +5 -0
  15. package/dist/components/alert-icon/alert-icon.d.ts.map +1 -1
  16. package/dist/components/alert-icon/alert-icon.js +26 -0
  17. package/dist/components/alert-icon/alert-icon.js.map +1 -1
  18. package/dist/integration-systems/integration-button/integration-button.css.js +20 -13
  19. package/dist/integration-systems/integration-button/integration-button.css.js.map +1 -1
  20. package/dist/integration-systems/integration-button/integration-button.d.ts +1 -1
  21. package/dist/integration-systems/integration-button/integration-button.js +1 -1
  22. package/dist/integration-systems/integration-button/integration-button.js.map +1 -1
  23. package/dist/integration-systems/integration-dropdown-button/integration-dropdown-button.css.js +1 -0
  24. package/dist/integration-systems/integration-dropdown-button/integration-dropdown-button.css.js.map +1 -1
  25. package/dist/openbridge.css +0 -73
  26. package/dist/palettes/blinking.d.ts +6 -0
  27. package/dist/palettes/blinking.d.ts.map +1 -0
  28. package/dist/palettes/blinking.js +44 -0
  29. package/dist/palettes/blinking.js.map +1 -0
  30. package/package.json +4 -2
  31. package/script/agent-docs/emitters.ts +189 -0
  32. package/script/agent-docs/frontmatter.ts +118 -0
  33. package/script/check-slot-event-docs.ts +2 -2
  34. package/script/sync-agent-docs.test.ts +298 -0
  35. package/script/sync-agent-docs.ts +156 -0
  36. package/src/components/alert-button/alert-button.spec.ts +58 -0
  37. package/src/components/alert-button/alert-button.ts +16 -0
  38. package/src/components/alert-frame/alert-frame.css +1 -0
  39. package/src/components/alert-frame/alert-frame.spec.ts +122 -0
  40. package/src/components/alert-frame/alert-frame.stories.ts +12 -0
  41. package/src/components/alert-frame/alert-frame.ts +37 -0
  42. package/src/components/alert-icon/alert-icon.spec.ts +76 -0
  43. package/src/components/alert-icon/alert-icon.ts +38 -0
  44. package/src/icons/AGENTS.md +6 -0
  45. package/src/integration-systems/integration-button/integration-button.css +20 -13
  46. package/src/integration-systems/integration-button/integration-button.stories.ts +70 -44
  47. package/src/integration-systems/integration-button/integration-button.ts +2 -2
  48. package/src/integration-systems/integration-dropdown-button/integration-dropdown-button.css +1 -0
  49. package/src/palettes/blinking.ts +46 -0
  50. package/src/palettes/manual.css +0 -42
  51. package/src/palettes/variables.css +0 -36
@@ -16,7 +16,7 @@ export declare enum IntegrationButtonType {
16
16
  /**
17
17
  * `<obc-integration-button>` – A button component for integration systems.
18
18
  *
19
- * @slot leading-icon - Icon before label (shown when `hasLeadingIcon` is true)
19
+ * @slot leading-icon - Icon before label (shown when `hasLeadingIcon` is true); rendered at the large icon size when `hasStatus` is true
20
20
  * @slot trailing-icon - Icon after label (shown when `hasTrailingIcon` is true)
21
21
  * @slot trailing-icon2 - Icon after label (shown when `hasTrailingIcon2` is true)
22
22
  * @slot label - Label text
@@ -46,7 +46,7 @@ let ObcIntegrationButton = class extends LitElement {
46
46
  selected: this.selected,
47
47
  activated: this.activated,
48
48
  disabled: this.disabled,
49
- "has-description": this.hasStatus,
49
+ "has-status": this.hasStatus,
50
50
  ["variant-" + this.variant]: true,
51
51
  ["type-" + this.type]: true
52
52
  };
@@ -1 +1 @@
1
- {"version":3,"file":"integration-button.js","sources":["../../../src/integration-systems/integration-button/integration-button.ts"],"sourcesContent":["import {LitElement, html, nothing, unsafeCSS} from 'lit';\nimport {customElement} from '../../decorator.js';\nimport compentStyle from './integration-button.css?inline';\nimport {property} from 'lit/decorators.js';\nimport {classMap} from 'lit/directives/class-map.js';\n\nexport interface IntegrationButtonReadout {\n label: string;\n value: string;\n unit: string;\n}\n\nexport enum IntegrationButtonVariant {\n normal = 'normal',\n flat = 'flat',\n}\n\nexport enum IntegrationButtonType {\n hug = 'hug',\n regular = 'regular',\n rich = 'rich',\n}\n\n/**\n * `<obc-integration-button>` – A button component for integration systems.\n *\n * @slot leading-icon - Icon before label (shown when `hasLeadingIcon` is true)\n * @slot trailing-icon - Icon after label (shown when `hasTrailingIcon` is true)\n * @slot trailing-icon2 - Icon after label (shown when `hasTrailingIcon2` is true)\n * @slot label - Label text\n * @slot status - Status/description text (shown when `hasStatus` is true)\n * @slot info-label - Info label text\n * @slot info-status - Info status text\n * @slot integration-vessel-menu - Integration vessel menu to be shown when button is in activated state\n *\n * @fires click - Fired when the internal button is activated.\n *\n * @experimental\n */\n@customElement('obc-integration-button')\nexport class ObcIntegrationButton extends LitElement {\n /** Shows the `trailing-icon` slot. */\n @property({type: Boolean}) hasTrailingIcon = false;\n /**\n * Shows the `trailing-icon2` slot.\n * @availableWhen hasTrailingIcon==true\n */\n @property({type: Boolean}) hasTrailingIcon2 = false;\n /** Shows the `leading-icon` slot. */\n @property({type: Boolean}) hasLeadingIcon = false;\n /** Shows the `status` slot. */\n @property({type: Boolean}) hasStatus = false;\n /** List of readout items shown in the rich type. */\n @property({type: Array, attribute: false})\n readouts: IntegrationButtonReadout[] = [];\n /** Disables the internal button. */\n @property({type: Boolean}) disabled = false;\n /** Applies active state styling while a selection is pending. */\n @property({type: Boolean}) activated = false;\n /** Applies selected state styling. */\n @property({type: Boolean}) selected = false;\n /** Shows a bottom divider under the button. */\n @property({type: Boolean}) dividerBottom = false;\n /** Shows a right divider to separate from adjacent buttons. */\n @property({type: Boolean}) dividerRight = false;\n /** Visual variant (`normal` or `flat`). */\n @property({type: String}) variant: IntegrationButtonVariant =\n IntegrationButtonVariant.normal;\n /** Layout type (`hug`, `regular`, or `rich`). */\n @property({type: String}) type: IntegrationButtonType =\n IntegrationButtonType.regular;\n\n private getButtonClasses() {\n return {\n 'touch-target': true,\n selected: this.selected,\n activated: this.activated,\n disabled: this.disabled,\n 'has-description': this.hasStatus,\n ['variant-' + this.variant]: true,\n ['type-' + this.type]: true,\n };\n }\n\n private onIntegrationVesselMenuClick(event: Event) {\n event.stopPropagation();\n }\n\n renderRich() {\n return html`\n <div class=\"button-horizontal-divider-container\">\n <div class=\"button-vertical-divider-container\">\n <button\n class=${classMap(this.getButtonClasses())}\n ?disabled=${this.disabled}\n >\n <div class=\"content-container\">\n <div class=\"main-container\">\n ${this.hasLeadingIcon\n ? html`<div class=\"icon leading\">\n <slot name=\"leading-icon\"></slot>\n </div>`\n : nothing}\n <div class=\"text-container\">\n <div class=\"label\"><slot name=\"label\"></slot></div>\n ${this.hasStatus\n ? html`<div class=\"status\">\n <slot name=\"status\"></slot>\n </div>`\n : nothing}\n </div>\n ${this.hasTrailingIcon\n ? html`<div class=\"icon-container\">\n ${this.hasTrailingIcon2\n ? html`<slot\n name=\"trailing-icon2\"\n class=\"icon trailing\"\n ></slot>`\n : nothing}\n <slot name=\"trailing-icon\" class=\"icon trailing\"></slot>\n </div>`\n : nothing}\n </div>\n <div class=\"info-container\">\n <div class=\"info-item\">\n <slot class=\"info-label\" name=\"info-label\"></slot>\n <slot class=\"info-status\" name=\"info-status\"></slot>\n </div>\n ${this.readouts.map(\n (readout) => html`\n <div class=\"info-readout-item\">\n <div class=\"info-item-label\">${readout.label}</div>\n <div class=\"info-item-value\">${readout.value}</div>\n <div class=\"info-item-unit\">${readout.unit}</div>\n </div>\n `\n )}\n </div>\n </div>\n </button>\n ${this.dividerRight\n ? html`<div class=\"divider-right\"></div>`\n : html`<div\n class=\"divider-right\"\n style=\"visibility: hidden;\"\n ></div>`}\n </div>\n ${this.dividerBottom\n ? html`<div class=\"divider-bottom\"></div>`\n : nothing}\n </div>\n <div\n class=${classMap({\n 'integration-vessel-menu-container': true,\n show: this.activated,\n })}\n @click=${this.onIntegrationVesselMenuClick}\n >\n <slot name=\"integration-vessel-menu\"></slot>\n </div>\n `;\n }\n\n renderRegular() {\n return html`\n <div class=\"button-vertical-divider-container\">\n <button\n class=${classMap(this.getButtonClasses())}\n ?disabled=${this.disabled}\n >\n <div class=\"content-container\">\n ${this.hasLeadingIcon\n ? html`<div class=\"icon leading\">\n <slot name=\"leading-icon\"></slot>\n </div>`\n : nothing}\n <div class=\"text-container\">\n <div class=\"label\"><slot name=\"label\"></slot></div>\n ${this.hasStatus\n ? html`<div class=\"status\"><slot name=\"status\"></slot></div>`\n : nothing}\n </div>\n ${this.hasTrailingIcon\n ? html`<div class=\"icon-container\">\n ${this.hasTrailingIcon2\n ? html`<slot\n name=\"trailing-icon2\"\n class=\"icon trailing\"\n ></slot>`\n : nothing}\n <slot name=\"trailing-icon\" class=\"icon trailing\"></slot>\n </div>`\n : nothing}\n </div>\n </button>\n ${this.dividerRight\n ? html`<div class=\"divider-right\"></div>`\n : html`<div class=\"divider-right\" style=\"visibility: hidden;\"></div>`}\n </div>\n <div\n class=${classMap({\n 'integration-vessel-menu-container': true,\n show: this.activated,\n })}\n @click=${this.onIntegrationVesselMenuClick}\n >\n <slot name=\"integration-vessel-menu\"></slot>\n </div>\n `;\n }\n\n renderHug() {\n return html`\n <div class=\"button-vertical-divider-container\">\n <button\n class=${classMap(this.getButtonClasses())}\n ?disabled=${this.disabled}\n >\n <div class=\"content-container\">\n ${this.hasLeadingIcon\n ? html`<div class=\"icon leading\">\n <slot name=\"leading-icon\"></slot>\n </div>`\n : nothing}\n <div class=\"text-container\">\n <div class=\"label\"><slot name=\"label\"></slot></div>\n ${this.hasStatus\n ? html`<div class=\"status\"><slot name=\"status\"></slot></div>`\n : nothing}\n </div>\n ${this.hasTrailingIcon\n ? html`<div class=\"icon-container\">\n ${this.hasTrailingIcon2\n ? html`<slot\n name=\"trailing-icon2\"\n class=\"icon trailing\"\n ></slot>`\n : nothing}\n <slot name=\"trailing-icon\" class=\"icon trailing\"></slot>\n </div>`\n : nothing}\n </div>\n </button>\n ${this.dividerRight\n ? html`<div class=\"divider-right\"></div>`\n : html`<div class=\"divider-right\" style=\"visibility: hidden;\"></div>`}\n </div>\n <div\n class=${classMap({\n 'integration-vessel-menu-container': true,\n show: this.activated,\n })}\n @click=${this.onIntegrationVesselMenuClick}\n >\n <slot name=\"integration-vessel-menu\"></slot>\n </div>\n `;\n }\n\n override render() {\n switch (this.type) {\n case IntegrationButtonType.hug: {\n return this.renderHug();\n }\n case IntegrationButtonType.rich: {\n return this.renderRich();\n }\n case IntegrationButtonType.regular:\n default: {\n return this.renderRegular();\n }\n }\n }\n\n static override styles = unsafeCSS(compentStyle);\n\n override updated() {\n let dividerHeight = 40;\n if (this.type === IntegrationButtonType.hug) {\n dividerHeight = 32;\n }\n if (this.type === IntegrationButtonType.rich) {\n dividerHeight = 64;\n }\n this.style.setProperty(\n '--integration-button-divider-height',\n `${dividerHeight}px`\n );\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-integration-button': ObcIntegrationButton;\n }\n}\n"],"names":["IntegrationButtonVariant","IntegrationButtonType"],"mappings":"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"}
1
+ {"version":3,"file":"integration-button.js","sources":["../../../src/integration-systems/integration-button/integration-button.ts"],"sourcesContent":["import {LitElement, html, nothing, unsafeCSS} from 'lit';\nimport {customElement} from '../../decorator.js';\nimport compentStyle from './integration-button.css?inline';\nimport {property} from 'lit/decorators.js';\nimport {classMap} from 'lit/directives/class-map.js';\n\nexport interface IntegrationButtonReadout {\n label: string;\n value: string;\n unit: string;\n}\n\nexport enum IntegrationButtonVariant {\n normal = 'normal',\n flat = 'flat',\n}\n\nexport enum IntegrationButtonType {\n hug = 'hug',\n regular = 'regular',\n rich = 'rich',\n}\n\n/**\n * `<obc-integration-button>` – A button component for integration systems.\n *\n * @slot leading-icon - Icon before label (shown when `hasLeadingIcon` is true); rendered at the large icon size when `hasStatus` is true\n * @slot trailing-icon - Icon after label (shown when `hasTrailingIcon` is true)\n * @slot trailing-icon2 - Icon after label (shown when `hasTrailingIcon2` is true)\n * @slot label - Label text\n * @slot status - Status/description text (shown when `hasStatus` is true)\n * @slot info-label - Info label text\n * @slot info-status - Info status text\n * @slot integration-vessel-menu - Integration vessel menu to be shown when button is in activated state\n *\n * @fires click - Fired when the internal button is activated.\n *\n * @experimental\n */\n@customElement('obc-integration-button')\nexport class ObcIntegrationButton extends LitElement {\n /** Shows the `trailing-icon` slot. */\n @property({type: Boolean}) hasTrailingIcon = false;\n /**\n * Shows the `trailing-icon2` slot.\n * @availableWhen hasTrailingIcon==true\n */\n @property({type: Boolean}) hasTrailingIcon2 = false;\n /** Shows the `leading-icon` slot. */\n @property({type: Boolean}) hasLeadingIcon = false;\n /** Shows the `status` slot. */\n @property({type: Boolean}) hasStatus = false;\n /** List of readout items shown in the rich type. */\n @property({type: Array, attribute: false})\n readouts: IntegrationButtonReadout[] = [];\n /** Disables the internal button. */\n @property({type: Boolean}) disabled = false;\n /** Applies active state styling while a selection is pending. */\n @property({type: Boolean}) activated = false;\n /** Applies selected state styling. */\n @property({type: Boolean}) selected = false;\n /** Shows a bottom divider under the button. */\n @property({type: Boolean}) dividerBottom = false;\n /** Shows a right divider to separate from adjacent buttons. */\n @property({type: Boolean}) dividerRight = false;\n /** Visual variant (`normal` or `flat`). */\n @property({type: String}) variant: IntegrationButtonVariant =\n IntegrationButtonVariant.normal;\n /** Layout type (`hug`, `regular`, or `rich`). */\n @property({type: String}) type: IntegrationButtonType =\n IntegrationButtonType.regular;\n\n private getButtonClasses() {\n return {\n 'touch-target': true,\n selected: this.selected,\n activated: this.activated,\n disabled: this.disabled,\n 'has-status': this.hasStatus,\n ['variant-' + this.variant]: true,\n ['type-' + this.type]: true,\n };\n }\n\n private onIntegrationVesselMenuClick(event: Event) {\n event.stopPropagation();\n }\n\n renderRich() {\n return html`\n <div class=\"button-horizontal-divider-container\">\n <div class=\"button-vertical-divider-container\">\n <button\n class=${classMap(this.getButtonClasses())}\n ?disabled=${this.disabled}\n >\n <div class=\"content-container\">\n <div class=\"main-container\">\n ${this.hasLeadingIcon\n ? html`<div class=\"icon leading\">\n <slot name=\"leading-icon\"></slot>\n </div>`\n : nothing}\n <div class=\"text-container\">\n <div class=\"label\"><slot name=\"label\"></slot></div>\n ${this.hasStatus\n ? html`<div class=\"status\">\n <slot name=\"status\"></slot>\n </div>`\n : nothing}\n </div>\n ${this.hasTrailingIcon\n ? html`<div class=\"icon-container\">\n ${this.hasTrailingIcon2\n ? html`<slot\n name=\"trailing-icon2\"\n class=\"icon trailing\"\n ></slot>`\n : nothing}\n <slot name=\"trailing-icon\" class=\"icon trailing\"></slot>\n </div>`\n : nothing}\n </div>\n <div class=\"info-container\">\n <div class=\"info-item\">\n <slot class=\"info-label\" name=\"info-label\"></slot>\n <slot class=\"info-status\" name=\"info-status\"></slot>\n </div>\n ${this.readouts.map(\n (readout) => html`\n <div class=\"info-readout-item\">\n <div class=\"info-item-label\">${readout.label}</div>\n <div class=\"info-item-value\">${readout.value}</div>\n <div class=\"info-item-unit\">${readout.unit}</div>\n </div>\n `\n )}\n </div>\n </div>\n </button>\n ${this.dividerRight\n ? html`<div class=\"divider-right\"></div>`\n : html`<div\n class=\"divider-right\"\n style=\"visibility: hidden;\"\n ></div>`}\n </div>\n ${this.dividerBottom\n ? html`<div class=\"divider-bottom\"></div>`\n : nothing}\n </div>\n <div\n class=${classMap({\n 'integration-vessel-menu-container': true,\n show: this.activated,\n })}\n @click=${this.onIntegrationVesselMenuClick}\n >\n <slot name=\"integration-vessel-menu\"></slot>\n </div>\n `;\n }\n\n renderRegular() {\n return html`\n <div class=\"button-vertical-divider-container\">\n <button\n class=${classMap(this.getButtonClasses())}\n ?disabled=${this.disabled}\n >\n <div class=\"content-container\">\n ${this.hasLeadingIcon\n ? html`<div class=\"icon leading\">\n <slot name=\"leading-icon\"></slot>\n </div>`\n : nothing}\n <div class=\"text-container\">\n <div class=\"label\"><slot name=\"label\"></slot></div>\n ${this.hasStatus\n ? html`<div class=\"status\"><slot name=\"status\"></slot></div>`\n : nothing}\n </div>\n ${this.hasTrailingIcon\n ? html`<div class=\"icon-container\">\n ${this.hasTrailingIcon2\n ? html`<slot\n name=\"trailing-icon2\"\n class=\"icon trailing\"\n ></slot>`\n : nothing}\n <slot name=\"trailing-icon\" class=\"icon trailing\"></slot>\n </div>`\n : nothing}\n </div>\n </button>\n ${this.dividerRight\n ? html`<div class=\"divider-right\"></div>`\n : html`<div class=\"divider-right\" style=\"visibility: hidden;\"></div>`}\n </div>\n <div\n class=${classMap({\n 'integration-vessel-menu-container': true,\n show: this.activated,\n })}\n @click=${this.onIntegrationVesselMenuClick}\n >\n <slot name=\"integration-vessel-menu\"></slot>\n </div>\n `;\n }\n\n renderHug() {\n return html`\n <div class=\"button-vertical-divider-container\">\n <button\n class=${classMap(this.getButtonClasses())}\n ?disabled=${this.disabled}\n >\n <div class=\"content-container\">\n ${this.hasLeadingIcon\n ? html`<div class=\"icon leading\">\n <slot name=\"leading-icon\"></slot>\n </div>`\n : nothing}\n <div class=\"text-container\">\n <div class=\"label\"><slot name=\"label\"></slot></div>\n ${this.hasStatus\n ? html`<div class=\"status\"><slot name=\"status\"></slot></div>`\n : nothing}\n </div>\n ${this.hasTrailingIcon\n ? html`<div class=\"icon-container\">\n ${this.hasTrailingIcon2\n ? html`<slot\n name=\"trailing-icon2\"\n class=\"icon trailing\"\n ></slot>`\n : nothing}\n <slot name=\"trailing-icon\" class=\"icon trailing\"></slot>\n </div>`\n : nothing}\n </div>\n </button>\n ${this.dividerRight\n ? html`<div class=\"divider-right\"></div>`\n : html`<div class=\"divider-right\" style=\"visibility: hidden;\"></div>`}\n </div>\n <div\n class=${classMap({\n 'integration-vessel-menu-container': true,\n show: this.activated,\n })}\n @click=${this.onIntegrationVesselMenuClick}\n >\n <slot name=\"integration-vessel-menu\"></slot>\n </div>\n `;\n }\n\n override render() {\n switch (this.type) {\n case IntegrationButtonType.hug: {\n return this.renderHug();\n }\n case IntegrationButtonType.rich: {\n return this.renderRich();\n }\n case IntegrationButtonType.regular:\n default: {\n return this.renderRegular();\n }\n }\n }\n\n static override styles = unsafeCSS(compentStyle);\n\n override updated() {\n let dividerHeight = 40;\n if (this.type === IntegrationButtonType.hug) {\n dividerHeight = 32;\n }\n if (this.type === IntegrationButtonType.rich) {\n dividerHeight = 64;\n }\n this.style.setProperty(\n '--integration-button-divider-height',\n `${dividerHeight}px`\n );\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-integration-button': ObcIntegrationButton;\n }\n}\n"],"names":["IntegrationButtonVariant","IntegrationButtonType"],"mappings":"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"}
@@ -279,6 +279,7 @@ const compentStyle = css`* {
279
279
  flex-direction: column;
280
280
  align-items: flex-start;
281
281
  flex-grow: 1;
282
+ text-align: left;
282
283
  }
283
284
 
284
285
  :is(.wrapper option:not(.fleet-option)) .text-container .label {
@@ -1 +1 @@
1
- {"version":3,"file":"integration-dropdown-button.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"integration-dropdown-button.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -14739,36 +14739,6 @@
14739
14739
  inherits: true;
14740
14740
  initial-value: 0;
14741
14741
  }
14742
- @keyframes warning-blink {
14743
- 0% {
14744
- --warning-blink-on: 1;
14745
- --warning-blink-off: 0;
14746
- --alarm-blink-on: 1;
14747
- --alarm-blink-off: 0;
14748
- }
14749
-
14750
- 25% {
14751
- --alarm-blink-on: 0;
14752
- --alarm-blink-off: 1;
14753
- }
14754
-
14755
- 50% {
14756
- --warning-blink-on: 0;
14757
- --warning-blink-off: 1;
14758
- --alarm-blink-on: 1;
14759
- --alarm-blink-off: 0;
14760
- }
14761
-
14762
- 75% {
14763
- --alarm-blink-on: 0;
14764
- --alarm-blink-off: 1;
14765
- }
14766
-
14767
- 100% {
14768
- --warning-blink-on: 1;
14769
- --warning-blink-off: 0;
14770
- }
14771
- }
14772
14742
  @property --warning-blink-on {
14773
14743
  syntax: "<number>";
14774
14744
  inherits: true;
@@ -14779,10 +14749,6 @@
14779
14749
  inherits: true;
14780
14750
  initial-value: 0;
14781
14751
  }
14782
- :root {
14783
- animation: warning-blink 4s infinite;
14784
- animation-timing-function: steps(1);
14785
- }
14786
14752
  :root[data-obc-theme="day"] {
14787
14753
  --critical-enabled-background-color: rgb(196, 36, 183);
14788
14754
  --critical-enabled-border-color: rgb(153, 0, 143);
@@ -14899,45 +14865,6 @@
14899
14865
  inherits: true;
14900
14866
  initial-value: 0;
14901
14867
  }
14902
- @keyframes critical-blink {
14903
- 0% {
14904
- --critical-blink-on: 1;
14905
- --critical-blink-off: 0;
14906
- }
14907
-
14908
- 50% {
14909
- --critical-blink-on: 0;
14910
- --critical-blink-off: 1;
14911
- }
14912
-
14913
- 100% {
14914
- --critical-blink-on: 1;
14915
- --critical-blink-off: 0;
14916
- }
14917
- }
14918
- @keyframes low-blink {
14919
- 0% {
14920
- --low-blink-on: 1;
14921
- --low-blink-off: 0;
14922
- }
14923
-
14924
- 50% {
14925
- --low-blink-on: 0;
14926
- --low-blink-off: 1;
14927
- }
14928
-
14929
- 100% {
14930
- --low-blink-on: 1;
14931
- --low-blink-off: 0;
14932
- }
14933
- }
14934
- :root {
14935
- animation:
14936
- warning-blink 4s infinite,
14937
- critical-blink 1s infinite,
14938
- low-blink 8s infinite;
14939
- animation-timing-function: steps(1);
14940
- }
14941
14868
  .obc-radio-button {
14942
14869
  user-select: none;
14943
14870
 
@@ -0,0 +1,6 @@
1
+ export declare function blinkingCritical(el: HTMLElement): () => void;
2
+ export declare function blinkingAlarm(el: HTMLElement): () => void;
3
+ export declare function blinkingWarning(el: HTMLElement): () => void;
4
+ export declare function blinkingLow(el: HTMLElement): () => void;
5
+ export declare function blinkingAll(el: HTMLElement): () => void;
6
+ //# sourceMappingURL=blinking.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blinking.d.ts","sourceRoot":"","sources":["../../src/palettes/blinking.ts"],"names":[],"mappings":"AAqBA,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,WAAW,GAAG,MAAM,IAAI,CAE5D;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,WAAW,GAAG,MAAM,IAAI,CAEzD;AAED,wBAAgB,eAAe,CAAC,EAAE,EAAE,WAAW,GAAG,MAAM,IAAI,CAE3D;AAED,wBAAgB,WAAW,CAAC,EAAE,EAAE,WAAW,GAAG,MAAM,IAAI,CAEvD;AAED,wBAAgB,WAAW,CAAC,EAAE,EAAE,WAAW,GAAG,MAAM,IAAI,CAQvD"}
@@ -0,0 +1,44 @@
1
+ const CRITICAL_PERIOD = 1e3;
2
+ const ALARM_PERIOD = 2e3;
3
+ const WARNING_PERIOD = 4e3;
4
+ const LOW_PERIOD = 8e3;
5
+ function blinkingInstall(el, period, label) {
6
+ const anim = el.animate(
7
+ [
8
+ { [label + "-on"]: 1, [label + "-off"]: 0 },
9
+ { [label + "-on"]: 0, [label + "-off"]: 1 }
10
+ ],
11
+ { duration: period, iterations: Infinity, easing: "steps(2, jump-none)" }
12
+ );
13
+ anim.startTime = 0;
14
+ return () => anim.cancel();
15
+ }
16
+ function blinkingCritical(el) {
17
+ return blinkingInstall(el, CRITICAL_PERIOD, "--critical-blink");
18
+ }
19
+ function blinkingAlarm(el) {
20
+ return blinkingInstall(el, ALARM_PERIOD, "--alarm-blink");
21
+ }
22
+ function blinkingWarning(el) {
23
+ return blinkingInstall(el, WARNING_PERIOD, "--warning-blink");
24
+ }
25
+ function blinkingLow(el) {
26
+ return blinkingInstall(el, LOW_PERIOD, "--low-blink");
27
+ }
28
+ function blinkingAll(el) {
29
+ const animes = [
30
+ blinkingCritical(el),
31
+ blinkingAlarm(el),
32
+ blinkingWarning(el),
33
+ blinkingLow(el)
34
+ ];
35
+ return () => animes.forEach((anim) => anim());
36
+ }
37
+ export {
38
+ blinkingAlarm,
39
+ blinkingAll,
40
+ blinkingCritical,
41
+ blinkingLow,
42
+ blinkingWarning
43
+ };
44
+ //# sourceMappingURL=blinking.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blinking.js","sources":["../../src/palettes/blinking.ts"],"sourcesContent":["const CRITICAL_PERIOD = 1000; // ms\nconst ALARM_PERIOD = 2000; // ms\nconst WARNING_PERIOD = 4000; // ms\nconst LOW_PERIOD = 8000; // ms\n\nfunction blinkingInstall(\n el: HTMLElement,\n period: number,\n label: string\n): () => void {\n const anim = el.animate(\n [\n {[label + '-on']: 1, [label + '-off']: 0},\n {[label + '-on']: 0, [label + '-off']: 1},\n ],\n {duration: period, iterations: Infinity, easing: 'steps(2, jump-none)'}\n );\n anim.startTime = 0; // Common time origin for all animations, so they blink in sync.\n return () => anim.cancel();\n}\n\nexport function blinkingCritical(el: HTMLElement): () => void {\n return blinkingInstall(el, CRITICAL_PERIOD, '--critical-blink');\n}\n\nexport function blinkingAlarm(el: HTMLElement): () => void {\n return blinkingInstall(el, ALARM_PERIOD, '--alarm-blink');\n}\n\nexport function blinkingWarning(el: HTMLElement): () => void {\n return blinkingInstall(el, WARNING_PERIOD, '--warning-blink');\n}\n\nexport function blinkingLow(el: HTMLElement): () => void {\n return blinkingInstall(el, LOW_PERIOD, '--low-blink');\n}\n\nexport function blinkingAll(el: HTMLElement): () => void {\n const animes = [\n blinkingCritical(el),\n blinkingAlarm(el),\n blinkingWarning(el),\n blinkingLow(el),\n ];\n return () => animes.forEach((anim) => anim());\n}\n"],"names":[],"mappings":"AAAA,MAAM,kBAAkB;AACxB,MAAM,eAAe;AACrB,MAAM,iBAAiB;AACvB,MAAM,aAAa;AAEnB,SAAS,gBACP,IACA,QACA,OACY;AACZ,QAAM,OAAO,GAAG;AAAA,IACd;AAAA,MACE,EAAC,CAAC,QAAQ,KAAK,GAAG,GAAG,CAAC,QAAQ,MAAM,GAAG,EAAA;AAAA,MACvC,EAAC,CAAC,QAAQ,KAAK,GAAG,GAAG,CAAC,QAAQ,MAAM,GAAG,EAAA;AAAA,IAAC;AAAA,IAE1C,EAAC,UAAU,QAAQ,YAAY,UAAU,QAAQ,sBAAA;AAAA,EAAqB;AAExE,OAAK,YAAY;AACjB,SAAO,MAAM,KAAK,OAAA;AACpB;AAEO,SAAS,iBAAiB,IAA6B;AAC5D,SAAO,gBAAgB,IAAI,iBAAiB,kBAAkB;AAChE;AAEO,SAAS,cAAc,IAA6B;AACzD,SAAO,gBAAgB,IAAI,cAAc,eAAe;AAC1D;AAEO,SAAS,gBAAgB,IAA6B;AAC3D,SAAO,gBAAgB,IAAI,gBAAgB,iBAAiB;AAC9D;AAEO,SAAS,YAAY,IAA6B;AACvD,SAAO,gBAAgB,IAAI,YAAY,aAAa;AACtD;AAEO,SAAS,YAAY,IAA6B;AACvD,QAAM,SAAS;AAAA,IACb,iBAAiB,EAAE;AAAA,IACnB,cAAc,EAAE;AAAA,IAChB,gBAAgB,EAAE;AAAA,IAClB,YAAY,EAAE;AAAA,EAAA;AAEhB,SAAO,MAAM,OAAO,QAAQ,CAAC,SAAS,MAAM;AAC9C;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oicl/openbridge-webcomponents-full-bundle",
3
- "version": "2.0.0-next.119",
3
+ "version": "2.0.0-next.121",
4
4
  "type": "module",
5
5
  "repository": {
6
6
  "type": "git",
@@ -140,7 +140,9 @@
140
140
  "typecheck": "tsc --noEmit",
141
141
  "format": "prettier \"**/*.{cjs,html,js,json,md,ts,css}\" --write",
142
142
  "format:check": "prettier \"**/*.{cjs,html,js,json,md,ts,css}\" --check",
143
- "lint": "npm run lint:mixins && npm run lint:variables && npm run lint:icons && npm run lint:slots && npm run lint:lit-analyzer && npm run lint:eslint",
143
+ "lint": "npm run lint:mixins && npm run lint:variables && npm run lint:icons && npm run lint:slots && npm run lint:agents && npm run lint:lit-analyzer && npm run lint:eslint",
144
+ "agents:sync": "tsx ./script/sync-agent-docs.ts",
145
+ "lint:agents": "tsx ./script/sync-agent-docs.ts --check",
144
146
  "lint:mixins": "tsx ./script/check-css-mixins.ts",
145
147
  "lint:slots": "tsx ./script/check-slot-event-docs.ts",
146
148
  "lint:variables": "tsx ./script/check-css-variables.ts",
@@ -0,0 +1,189 @@
1
+ import type {AgentDoc} from './frontmatter.js';
2
+
3
+ export const ROUTING_MARKER = 'agents:routing';
4
+
5
+ const SYNC_CMD = 'npm run agents:sync -w packages/openbridge-webcomponents';
6
+
7
+ /**
8
+ * Rewrites sibling links so they still resolve from an adapter directory.
9
+ *
10
+ * Canonical docs link to each other by bare filename — `[jsdoc.md](jsdoc.md)` —
11
+ * which is correct inside `docs/agents/` and broken once the body is copied
12
+ * into `.github/instructions/` or `.cursor/rules/`, where the sibling is named
13
+ * `jsdoc.instructions.md` / `jsdoc.mdc` or does not exist at all.
14
+ *
15
+ * They are repointed at the canonical file rather than at the neighbouring
16
+ * adapter: the canonical doc is the thing a reader should land on, and one
17
+ * rewrite then works for every adapter. `.github/instructions/`, `.cursor/rules/`
18
+ * and `docs/agents/` are all two levels below the repository root, so links
19
+ * already written as `../../…` need no adjustment.
20
+ *
21
+ * Only names in `siblings` are touched, so an unrelated bare `.md` link is left
22
+ * alone instead of being silently repointed at a file that does not exist.
23
+ */
24
+ export function rewriteSiblingLinks(
25
+ body: string,
26
+ siblings: ReadonlySet<string>
27
+ ): string {
28
+ return body.replace(
29
+ /\]\((?!\.\.\/|\/|https?:)([A-Za-z0-9._-]+)\.md(#[^)]*)?\)/g,
30
+ (match, name: string, hash: string | undefined) =>
31
+ siblings.has(name)
32
+ ? `](../../docs/agents/${name}.md${hash ?? ''})`
33
+ : match
34
+ );
35
+ }
36
+
37
+ function banner(source: string): string {
38
+ return [
39
+ '<!-- GENERATED FILE — DO NOT EDIT.',
40
+ ` Source: ${source}`,
41
+ ` Regenerate: ${SYNC_CMD} -->`,
42
+ ].join('\n');
43
+ }
44
+
45
+ /**
46
+ * Copilot path-scoped instruction file: `applyTo` frontmatter plus the full
47
+ * body. The body is copied rather than referenced because a pointer would
48
+ * defeat the glob auto-attachment this file exists to provide.
49
+ */
50
+ export function renderInstructionsFile(
51
+ doc: AgentDoc,
52
+ siblings: ReadonlySet<string> = new Set()
53
+ ): string {
54
+ return [
55
+ '---',
56
+ `applyTo: "${doc.globs.join(',')}"`,
57
+ '---',
58
+ '',
59
+ banner(doc.sourcePath),
60
+ '',
61
+ rewriteSiblingLinks(doc.body, siblings).replace(/\n*$/, '\n'),
62
+ ].join('\n');
63
+ }
64
+
65
+ /**
66
+ * Cursor rule: `globs` + `alwaysApply: false` is Cursor's "Apply to Specific
67
+ * Files" type — the direct equivalent of Copilot's `applyTo`.
68
+ *
69
+ * `description` is deliberately omitted. Cursor's four rule types are distinct
70
+ * frontmatter combinations, and adding a description alongside globs selects
71
+ * "Apply Intelligently" (the agent decides) instead of deterministic
72
+ * attachment. The description still reaches the reader: the body opens with the
73
+ * document's own heading.
74
+ *
75
+ * Negative globs are dropped. Cursor documents `globs` as a comma-separated
76
+ * list and says nothing about `!` negation, so a pattern it cannot parse could
77
+ * take the whole line with it. The only doc affected is `jsdoc.md`, whose
78
+ * exclusions are generated directories a developer rarely opens by hand.
79
+ */
80
+ export function renderCursorRule(
81
+ doc: AgentDoc,
82
+ siblings: ReadonlySet<string> = new Set()
83
+ ): string {
84
+ const globs = doc.globs.filter((g) => !g.startsWith('!'));
85
+ return [
86
+ '---',
87
+ `globs: ${globs.join(',')}`,
88
+ 'alwaysApply: false',
89
+ '---',
90
+ '',
91
+ banner(doc.sourcePath),
92
+ '',
93
+ rewriteSiblingLinks(doc.body, siblings).replace(/\n*$/, '\n'),
94
+ ].join('\n');
95
+ }
96
+
97
+ /** Shared routing table (no markers) for AGENTS.md and copilot-instructions.md. */
98
+ export function renderRoutingTable(docs: AgentDoc[]): string {
99
+ const rows = [...docs]
100
+ .sort((a, b) => a.name.localeCompare(b.name))
101
+ .map((doc) => {
102
+ const scope = doc.globs.map((g) => `\`${g}\``).join('<br>');
103
+ return `| [${doc.name}](${doc.sourcePath}) | ${scope} | ${doc.description} |`;
104
+ });
105
+ return [
106
+ '| Doc | Scope (globs) | Description |',
107
+ '| --- | --- | --- |',
108
+ ...rows,
109
+ ].join('\n');
110
+ }
111
+
112
+ /**
113
+ * Repo-wide Copilot entry point. Unlike the path-scoped files this one carries
114
+ * no bodies — it has no globs of its own, so a pointer costs nothing here.
115
+ */
116
+ export function renderCopilotInstructions(docs: AgentDoc[]): string {
117
+ return [
118
+ banner('docs/agents/*.md'),
119
+ '',
120
+ '# GitHub Copilot Custom Instructions',
121
+ '',
122
+ '> **Canonical instructions live in [`AGENTS.md`](../AGENTS.md)**, and the',
123
+ '> path-scoped rules in [`docs/agents/`](../docs/agents/). This file exists',
124
+ '> because Copilot reads `.github/copilot-instructions.md` by convention.',
125
+ '',
126
+ 'This repository contains the Openbridge Web Components library, a collection',
127
+ 'of maritime navigation and automation UI components built with Lit and',
128
+ 'TypeScript.',
129
+ '',
130
+ '- **Start here →** [`AGENTS.md`](../AGENTS.md).',
131
+ '- Path-scoped rules are auto-attached from `.github/instructions/`, which is',
132
+ ' generated from `docs/agents/`. Read the canonical file, not the copy.',
133
+ '- Ask for clarification (e.g. a list of questions) before implementing',
134
+ ' significant changes.',
135
+ '',
136
+ '## Available Instruction Files',
137
+ '',
138
+ renderRoutingTable(docs),
139
+ '',
140
+ ].join('\n');
141
+ }
142
+
143
+ /**
144
+ * Claude Code entry point. Generated locally; stays gitignored.
145
+ *
146
+ * A pure pointer by design. Claude Code reads `CLAUDE.md` by convention, so the
147
+ * file exists to route it to the canonical instructions — it deliberately holds
148
+ * no rules of its own. Anything that applies to the whole team belongs in
149
+ * `AGENTS.md`; anything path-scoped belongs in `docs/agents/`. Neither is
150
+ * tool-specific, so neither belongs here.
151
+ */
152
+ export function renderClaudeMd(): string {
153
+ return [
154
+ banner('the agents:sync generator'),
155
+ '',
156
+ '# CLAUDE.md',
157
+ '',
158
+ 'All repository instructions live in **[AGENTS.md](AGENTS.md)** — read and',
159
+ 'follow it, including the path-scoped rules in',
160
+ '[`docs/agents/`](docs/agents/) that it routes to.',
161
+ '',
162
+ 'This file intentionally adds nothing of its own. It exists because Claude',
163
+ 'Code reads `CLAUDE.md` by convention; the instructions are tool-neutral and',
164
+ 'shared with every other agent.',
165
+ '',
166
+ ].join('\n');
167
+ }
168
+
169
+ /** Replaces the text between `<!-- marker:start -->` and `<!-- marker:end -->`. */
170
+ export function replaceMarkedBlock(
171
+ content: string,
172
+ marker: string,
173
+ replacement: string
174
+ ): string {
175
+ const start = `<!-- ${marker}:start -->`;
176
+ const end = `<!-- ${marker}:end -->`;
177
+ const startIdx = content.indexOf(start);
178
+ const endIdx = content.indexOf(end);
179
+ if (startIdx === -1 || endIdx === -1 || endIdx < startIdx) {
180
+ throw new Error(`markers "${start}" / "${end}" not found`);
181
+ }
182
+ return (
183
+ content.slice(0, startIdx + start.length) +
184
+ '\n' +
185
+ replacement +
186
+ '\n' +
187
+ content.slice(endIdx)
188
+ );
189
+ }
@@ -0,0 +1,118 @@
1
+ import path from 'node:path';
2
+
3
+ /** One canonical agent-instruction document under `docs/agents/`. */
4
+ export interface AgentDoc {
5
+ name: string;
6
+ description: string;
7
+ globs: string[];
8
+ body: string;
9
+ sourcePath: string;
10
+ }
11
+
12
+ const SCALAR_KEYS = ['name', 'description'] as const;
13
+ const LIST_KEYS = ['globs'] as const;
14
+
15
+ function unquote(value: string): string {
16
+ const trimmed = value.trim();
17
+ if (
18
+ (trimmed.startsWith("'") && trimmed.endsWith("'") && trimmed.length > 1) ||
19
+ (trimmed.startsWith('"') && trimmed.endsWith('"') && trimmed.length > 1)
20
+ ) {
21
+ return trimmed.slice(1, -1);
22
+ }
23
+ return trimmed;
24
+ }
25
+
26
+ /**
27
+ * Parses the strict frontmatter subset used by `docs/agents/*.md`.
28
+ *
29
+ * Deliberately not a YAML parser: it accepts `key: value` scalars and
30
+ * ` - item` lists for a fixed key set and throws on anything else, so a
31
+ * valid-but-unsupported construct can never be silently mis-emitted.
32
+ */
33
+ export function parseAgentDoc(raw: string, sourcePath: string): AgentDoc {
34
+ const lines = raw.split('\n');
35
+ if (lines[0].trim() !== '---') {
36
+ throw new Error(`${sourcePath}: must start with a "---" frontmatter block`);
37
+ }
38
+ const end = lines.indexOf('---', 1);
39
+ if (end === -1) {
40
+ throw new Error(`${sourcePath}: frontmatter block is never closed`);
41
+ }
42
+
43
+ const scalars = new Map<string, string>();
44
+ const lists = new Map<string, string[]>();
45
+ let currentList: string[] | null = null;
46
+
47
+ for (let i = 1; i < end; i++) {
48
+ const line = lines[i];
49
+ const lineNo = i + 1;
50
+ if (line.trim() === '') continue;
51
+
52
+ if (line.startsWith(' - ') || line.startsWith('- ')) {
53
+ if (!currentList) {
54
+ throw new Error(
55
+ `${sourcePath}: list item with no key on line ${lineNo}`
56
+ );
57
+ }
58
+ currentList.push(unquote(line.slice(line.indexOf('- ') + 2)));
59
+ continue;
60
+ }
61
+
62
+ const match = /^([A-Za-z][A-Za-z0-9_]*):(.*)$/.exec(line);
63
+ if (!match) {
64
+ throw new Error(`${sourcePath}: cannot parse line ${lineNo}: ${line}`);
65
+ }
66
+ const [, key, rest] = match;
67
+
68
+ if ((SCALAR_KEYS as readonly string[]).includes(key)) {
69
+ scalars.set(key, unquote(rest));
70
+ currentList = null;
71
+ } else if ((LIST_KEYS as readonly string[]).includes(key)) {
72
+ if (rest.trim() !== '') {
73
+ throw new Error(
74
+ `${sourcePath}: "${key}" must be a block list, not an inline value (line ${lineNo})`
75
+ );
76
+ }
77
+ currentList = [];
78
+ lists.set(key, currentList);
79
+ } else {
80
+ throw new Error(
81
+ `${sourcePath}: unsupported key "${key}" on line ${lineNo}`
82
+ );
83
+ }
84
+ }
85
+
86
+ for (const key of SCALAR_KEYS) {
87
+ if (!scalars.get(key)) {
88
+ throw new Error(
89
+ `${sourcePath}: "${key}" is required and must be non-empty`
90
+ );
91
+ }
92
+ }
93
+ const globs = lists.get('globs') ?? [];
94
+ if (globs.length === 0) {
95
+ throw new Error(`${sourcePath}: "globs" must list at least one pattern`);
96
+ }
97
+
98
+ const name = scalars.get('name')!;
99
+ const expected = path.basename(sourcePath, '.md');
100
+ if (name !== expected) {
101
+ throw new Error(
102
+ `${sourcePath}: name "${name}" does not match filename "${expected}"`
103
+ );
104
+ }
105
+
106
+ const body = lines
107
+ .slice(end + 1)
108
+ .join('\n')
109
+ .replace(/^\n+/, '');
110
+
111
+ return {
112
+ name,
113
+ description: scalars.get('description')!,
114
+ globs,
115
+ body,
116
+ sourcePath,
117
+ };
118
+ }
@@ -56,7 +56,7 @@
56
56
  * Dynamic slot names (`<slot name="${expr}">` or `<slot name="pre-${id}-post">`)
57
57
  * are skipped for the missing-slot check because their concrete names cannot be
58
58
  * known statically; document them with a placeholder tag such as
59
- * `@slot tab-<id>-icon` (see .cursor/rules/comments.mdc § Structured-tag rules).
59
+ * `@slot tab-<id>-icon` (see docs/agents/jsdoc.md § Structured-tag rules).
60
60
  *
61
61
  * Usage:
62
62
  * ```bash
@@ -413,7 +413,7 @@ async function run(): Promise<void> {
413
413
  printByFile(errors, (m) => console.error(m));
414
414
  console.error(
415
415
  `\n❌ Slot & event documentation audit failed. Add the missing @slot/@fires ` +
416
- `tags (or remove the phantom ones). See .cursor/rules/comments.mdc.`
416
+ `tags (or remove the phantom ones). See docs/agents/jsdoc.md.`
417
417
  );
418
418
  process.exitCode = 1;
419
419
  return;