@operato/input 10.29.63 → 10.29.67

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,16 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ### [10.29.67](https://github.com/hatiolab/operato/compare/v10.29.66...v10.29.67) (2026-11-02)
7
+
8
+
9
+ ### :rocket: New Features
10
+
11
+ * **input:** a select-buttons chip may show a count after its name ([2bc5f99](https://github.com/hatiolab/operato/commit/2bc5f998159c0a347681d9df4d00bcb85113ea75))
12
+ * **input:** select-buttons chips show pressed by their fill alone, without a checkmark ([534fd7c](https://github.com/hatiolab/operato/commit/534fd7c457b747816a1c2278a55e829822c3c4e6))
13
+
14
+
15
+
6
16
  ### [10.29.63](https://github.com/hatiolab/operato/compare/v10.29.62...v10.29.63) (2026-10-31)
7
17
 
8
18
 
@@ -15,6 +15,11 @@ type Option = {
15
15
  * 결과를 되짚어야 한다.
16
16
  */
17
17
  hint?: string;
18
+ /**
19
+ * How many rows the chip stands for, shown after the name (e.g. stages with the number of records in each). The
20
+ * page that knows the rows gives it; the chip only shows it, pressed or not.
21
+ */
22
+ count?: number;
18
23
  };
19
24
  export declare class OxInputSelectButtons extends OxFormField {
20
25
  static styles: import("lit").CSSResult[];
@@ -4,7 +4,7 @@
4
4
  import { __decorate } from "tslib";
5
5
  import '@material/web/chips/filter-chip.js';
6
6
  import '@material/web/chips/chip-set.js';
7
- import { css, html } from 'lit';
7
+ import { css, html, nothing } from 'lit';
8
8
  import { customElement, property } from 'lit/decorators.js';
9
9
  import { ifDefined } from 'lit/directives/if-defined.js';
10
10
  import { FORM_ELEMENT_HEIGHT_PLATFORM_EXCEPTIONS, suiteFormElementHeight } from '@operato/styles/form-element-heights.js';
@@ -38,6 +38,17 @@ let OxInputSelectButtons = class OxInputSelectButtons extends OxFormField {
38
38
  text-transform: var(--ox-input-select-buttons-label-text-transform, capitalize);
39
39
  }
40
40
 
41
+ md-filter-chip [slot='selected-icon'] {
42
+ display: none;
43
+ }
44
+
45
+ /* The count is the chip's figure: tabular so a row of chips does not jitter as the numbers change. */
46
+ .count {
47
+ margin-left: 6px;
48
+ font-variant-numeric: tabular-nums;
49
+ opacity: 0.72;
50
+ }
51
+
41
52
  :host {
42
53
  display: flex;
43
54
  flex-flow: row;
@@ -61,6 +72,12 @@ let OxInputSelectButtons = class OxInputSelectButtons extends OxFormField {
61
72
  --md-filter-chip-hover-label-text-color: var(--md-sys-color-on-surface);
62
73
  --md-filter-chip-hover-state-layer-opacity: 0.06;
63
74
 
75
+ /*
76
+ * No checkmark: the fill alone says a chip is pressed, so a chip keeps its width when pressed and a row of them
77
+ * does not shift. The empty selected-icon below takes the check's place, and the leading space stays the same.
78
+ */
79
+ --md-filter-chip-with-leading-icon-leading-space: 11px;
80
+
64
81
  /* 켜진 상태 — 채워서 확실히 다르게. 켜졌는지 아닌지가 헷갈리면 필터는 쓸모가 없다. */
65
82
  /* A pressed filter is a state, not a call to action: the soft container, not the accent fill. */
66
83
  --md-filter-chip-selected-container-color: var(--md-sys-color-secondary-container);
@@ -79,14 +96,15 @@ let OxInputSelectButtons = class OxInputSelectButtons extends OxFormField {
79
96
  const values = this.value instanceof Array ? this.value : typeof this.value == 'string' ? [this.value] : [];
80
97
  return html `
81
98
  <md-chip-set>
82
- ${(options || []).map(({ display, value, hint }) => html `
99
+ ${(options || []).map(({ display, value, hint, count }) => html `
83
100
  <md-filter-chip
84
101
  data-value=${value}
85
- label=${display}
102
+ label=${ifDefined(count === undefined ? display : undefined)}
86
103
  title=${ifDefined(hint)}
87
104
  ?selected=${values.includes(value)}
88
105
  @click=${(e) => !this.disabled && this.onClick(e)}
89
- ></md-filter-chip>
106
+ ><span slot="selected-icon"></span>${count === undefined ? nothing : html `${display}<span class="count">${count}</span>`}</md-filter-chip
107
+ >
90
108
  `)}
91
109
  </md-chip-set>
92
110
  `;
@@ -1 +1 @@
1
- {"version":3,"file":"ox-input-select-buttons.js","sourceRoot":"","sources":["../../src/ox-input-select-buttons.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @license Copyright © HatioLab Inc. All rights reserved.\n */\n\nimport '@material/web/chips/filter-chip.js'\nimport '@material/web/chips/chip-set.js'\n\nimport { css, html } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport { ifDefined } from 'lit/directives/if-defined.js'\n\nimport { FORM_ELEMENT_HEIGHT_PLATFORM_EXCEPTIONS, suiteFormElementHeight } from '@operato/styles/form-element-heights.js'\n\nimport { OxFormField } from './ox-form-field.js'\nimport { InputStyles } from './input-styles.js'\nimport { MdFilterChip } from '@material/web/chips/filter-chip.js'\n\ntype Option = {\n display: string\n value: string\n /**\n * 마우스를 올렸을 때 보이는 뜻.\n *\n * 칩의 이름은 짧아야 하는데, 이름만으로는 무엇이 걸러지는지 알 수 없는 것이 있다 — 「중요」가\n * 우선순위 몇 이상인지, 「만기」가 몇 시간 안인지. 그 값을 화면이 말하지 않으면 사용자는 눌러 보고\n * 결과를 되짚어야 한다.\n */\n hint?: string\n}\n\n@customElement('ox-input-select-buttons')\nexport class OxInputSelectButtons extends OxFormField {\n static styles = [\n InputStyles,\n css`\n /*\n * 필터는 **목록보다 조용해야 한다.**\n *\n * 확인해 보니 칩 글자가 16px 이었고 목록 본문은 14px 이었다. 걸러진 것이 하나도 없는 상태에서도 이\n * 줄이 화면에서 가장 크고 진했다. 테두리 색도 본문 글자와 같은 검정이라, 네 개가 나란히 서면\n * 그 선들이 제일 먼저 눈에 걸렸다.\n *\n * 그래서 꺼져 있을 때는 물러나고 켜져 있을 때만 나선다. 지금 무엇으로 걸렀는지가 이 줄에서\n * 바로 읽혀야 한다 — 목록이 짧아진 이유를 화면이 말해야 한다.\n *\n * md 칩을 갈아치우지 않고 그 토큰으로만 조정한다. 이 컴포넌트를 쓰는 화면이 많고, 자기 것으로\n * 다시 만들면 그 화면들이 두 모양으로 갈린다.\n */\n /* Labels that are identifiers (part names, codes) must show as written: set this to none. */\n md-filter-chip {\n text-transform: var(--ox-input-select-buttons-label-text-transform, capitalize);\n }\n\n :host {\n display: flex;\n flex-flow: row;\n flex-wrap: wrap;\n gap: 6px;\n\n /* Size: 26px on the platform, the small input height in the operato products. */\n --md-filter-chip-container-height: ${suiteFormElementHeight('--form-element-height-small', FORM_ELEMENT_HEIGHT_PLATFORM_EXCEPTIONS.selectButtonsChip)};\n --md-filter-chip-label-text-size: 12.5px;\n --md-filter-chip-label-text-weight: 560;\n --md-filter-chip-container-shape: calc(${suiteFormElementHeight('--form-element-height-small', FORM_ELEMENT_HEIGHT_PLATFORM_EXCEPTIONS.selectButtonsChip)} / 2);\n --md-filter-chip-leading-space: 11px;\n --md-filter-chip-trailing-space: 11px;\n --md-filter-chip-with-leading-icon-leading-space: 8px;\n --md-filter-chip-icon-size: 15px;\n\n /* 꺼진 상태 — 선은 흐리게, 글자는 보조 글자 색으로. */\n --md-filter-chip-outline-color: var(--md-sys-color-outline-variant);\n --md-filter-chip-outline-width: 1px;\n --md-filter-chip-label-text-color: var(--md-sys-color-on-surface-variant);\n --md-filter-chip-hover-label-text-color: var(--md-sys-color-on-surface);\n --md-filter-chip-hover-state-layer-opacity: 0.06;\n\n /* 켜진 상태 — 채워서 확실히 다르게. 켜졌는지 아닌지가 헷갈리면 필터는 쓸모가 없다. */\n /* A pressed filter is a state, not a call to action: the soft container, not the accent fill. */\n --md-filter-chip-selected-container-color: var(--md-sys-color-secondary-container);\n --md-filter-chip-selected-label-text-color: var(--md-sys-color-on-secondary-container);\n --md-filter-chip-selected-outline-width: 0px;\n --md-filter-chip-selected-focus-label-text-color: var(--md-sys-color-on-secondary-container);\n --md-filter-chip-selected-hover-label-text-color: var(--md-sys-color-on-secondary-container);\n --md-filter-chip-selected-pressed-label-text-color: var(--md-sys-color-on-secondary-container);\n --md-filter-chip-selected-leading-icon-color: var(--md-sys-color-on-secondary-container);\n --md-filter-chip-selected-hover-leading-icon-color: var(--md-sys-color-on-secondary-container);\n }\n `\n ]\n\n @property({ type: Array }) value: string[] | string | undefined = []\n @property({ type: Array }) options: Option[] = []\n @property({ type: Boolean }) multiple: boolean = false\n\n render() {\n const options = this.options.filter(option => !!option.value)\n const values = this.value instanceof Array ? this.value : typeof this.value == 'string' ? [this.value] : []\n\n return html`\n <md-chip-set>\n ${(options || []).map(\n ({ display, value, hint }) => html`\n <md-filter-chip\n data-value=${value}\n label=${display}\n title=${ifDefined(hint)}\n ?selected=${values.includes(value)}\n @click=${(e: MouseEvent | TouchEvent) => !this.disabled && this.onClick(e)}\n ></md-filter-chip>\n `\n )}\n </md-chip-set>\n `\n }\n\n onClick(e: MouseEvent | TouchEvent) {\n e.stopPropagation()\n\n const target = e.target as MdFilterChip\n const value = target.getAttribute('data-value') as string\n\n if (this.multiple) {\n const values = this.value instanceof Array ? this.value : typeof this.value == 'string' ? [this.value] : []\n\n const idx = (this.value || []).indexOf(value)\n if (idx != -1) {\n values.splice(idx, 1)\n } else {\n values.push(value)\n }\n this.value = [...values]\n } else {\n this.value = this.value === value ? undefined : value\n }\n\n this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true, detail: this.value }))\n }\n}\n"]}
1
+ {"version":3,"file":"ox-input-select-buttons.js","sourceRoot":"","sources":["../../src/ox-input-select-buttons.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @license Copyright © HatioLab Inc. All rights reserved.\n */\n\nimport '@material/web/chips/filter-chip.js'\nimport '@material/web/chips/chip-set.js'\n\nimport { css, html, nothing } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport { ifDefined } from 'lit/directives/if-defined.js'\n\nimport { FORM_ELEMENT_HEIGHT_PLATFORM_EXCEPTIONS, suiteFormElementHeight } from '@operato/styles/form-element-heights.js'\n\nimport { OxFormField } from './ox-form-field.js'\nimport { InputStyles } from './input-styles.js'\nimport { MdFilterChip } from '@material/web/chips/filter-chip.js'\n\ntype Option = {\n display: string\n value: string\n /**\n * 마우스를 올렸을 때 보이는 뜻.\n *\n * 칩의 이름은 짧아야 하는데, 이름만으로는 무엇이 걸러지는지 알 수 없는 것이 있다 — 「중요」가\n * 우선순위 몇 이상인지, 「만기」가 몇 시간 안인지. 그 값을 화면이 말하지 않으면 사용자는 눌러 보고\n * 결과를 되짚어야 한다.\n */\n hint?: string\n /**\n * How many rows the chip stands for, shown after the name (e.g. stages with the number of records in each). The\n * page that knows the rows gives it; the chip only shows it, pressed or not.\n */\n count?: number\n}\n\n@customElement('ox-input-select-buttons')\nexport class OxInputSelectButtons extends OxFormField {\n static styles = [\n InputStyles,\n css`\n /*\n * 필터는 **목록보다 조용해야 한다.**\n *\n * 확인해 보니 칩 글자가 16px 이었고 목록 본문은 14px 이었다. 걸러진 것이 하나도 없는 상태에서도 이\n * 줄이 화면에서 가장 크고 진했다. 테두리 색도 본문 글자와 같은 검정이라, 네 개가 나란히 서면\n * 그 선들이 제일 먼저 눈에 걸렸다.\n *\n * 그래서 꺼져 있을 때는 물러나고 켜져 있을 때만 나선다. 지금 무엇으로 걸렀는지가 이 줄에서\n * 바로 읽혀야 한다 — 목록이 짧아진 이유를 화면이 말해야 한다.\n *\n * md 칩을 갈아치우지 않고 그 토큰으로만 조정한다. 이 컴포넌트를 쓰는 화면이 많고, 자기 것으로\n * 다시 만들면 그 화면들이 두 모양으로 갈린다.\n */\n /* Labels that are identifiers (part names, codes) must show as written: set this to none. */\n md-filter-chip {\n text-transform: var(--ox-input-select-buttons-label-text-transform, capitalize);\n }\n\n md-filter-chip [slot='selected-icon'] {\n display: none;\n }\n\n /* The count is the chip's figure: tabular so a row of chips does not jitter as the numbers change. */\n .count {\n margin-left: 6px;\n font-variant-numeric: tabular-nums;\n opacity: 0.72;\n }\n\n :host {\n display: flex;\n flex-flow: row;\n flex-wrap: wrap;\n gap: 6px;\n\n /* Size: 26px on the platform, the small input height in the operato products. */\n --md-filter-chip-container-height: ${suiteFormElementHeight('--form-element-height-small', FORM_ELEMENT_HEIGHT_PLATFORM_EXCEPTIONS.selectButtonsChip)};\n --md-filter-chip-label-text-size: 12.5px;\n --md-filter-chip-label-text-weight: 560;\n --md-filter-chip-container-shape: calc(${suiteFormElementHeight('--form-element-height-small', FORM_ELEMENT_HEIGHT_PLATFORM_EXCEPTIONS.selectButtonsChip)} / 2);\n --md-filter-chip-leading-space: 11px;\n --md-filter-chip-trailing-space: 11px;\n --md-filter-chip-with-leading-icon-leading-space: 8px;\n --md-filter-chip-icon-size: 15px;\n\n /* 꺼진 상태 — 선은 흐리게, 글자는 보조 글자 색으로. */\n --md-filter-chip-outline-color: var(--md-sys-color-outline-variant);\n --md-filter-chip-outline-width: 1px;\n --md-filter-chip-label-text-color: var(--md-sys-color-on-surface-variant);\n --md-filter-chip-hover-label-text-color: var(--md-sys-color-on-surface);\n --md-filter-chip-hover-state-layer-opacity: 0.06;\n\n /*\n * No checkmark: the fill alone says a chip is pressed, so a chip keeps its width when pressed and a row of them\n * does not shift. The empty selected-icon below takes the check's place, and the leading space stays the same.\n */\n --md-filter-chip-with-leading-icon-leading-space: 11px;\n\n /* 켜진 상태 — 채워서 확실히 다르게. 켜졌는지 아닌지가 헷갈리면 필터는 쓸모가 없다. */\n /* A pressed filter is a state, not a call to action: the soft container, not the accent fill. */\n --md-filter-chip-selected-container-color: var(--md-sys-color-secondary-container);\n --md-filter-chip-selected-label-text-color: var(--md-sys-color-on-secondary-container);\n --md-filter-chip-selected-outline-width: 0px;\n --md-filter-chip-selected-focus-label-text-color: var(--md-sys-color-on-secondary-container);\n --md-filter-chip-selected-hover-label-text-color: var(--md-sys-color-on-secondary-container);\n --md-filter-chip-selected-pressed-label-text-color: var(--md-sys-color-on-secondary-container);\n --md-filter-chip-selected-leading-icon-color: var(--md-sys-color-on-secondary-container);\n --md-filter-chip-selected-hover-leading-icon-color: var(--md-sys-color-on-secondary-container);\n }\n `\n ]\n\n @property({ type: Array }) value: string[] | string | undefined = []\n @property({ type: Array }) options: Option[] = []\n @property({ type: Boolean }) multiple: boolean = false\n\n render() {\n const options = this.options.filter(option => !!option.value)\n const values = this.value instanceof Array ? this.value : typeof this.value == 'string' ? [this.value] : []\n\n return html`\n <md-chip-set>\n ${(options || []).map(\n ({ display, value, hint, count }) => html`\n <md-filter-chip\n data-value=${value}\n label=${ifDefined(count === undefined ? display : undefined)}\n title=${ifDefined(hint)}\n ?selected=${values.includes(value)}\n @click=${(e: MouseEvent | TouchEvent) => !this.disabled && this.onClick(e)}\n ><span slot=\"selected-icon\"></span>${count === undefined ? nothing : html`${display}<span class=\"count\">${count}</span>`}</md-filter-chip\n >\n `\n )}\n </md-chip-set>\n `\n }\n\n onClick(e: MouseEvent | TouchEvent) {\n e.stopPropagation()\n\n const target = e.target as MdFilterChip\n const value = target.getAttribute('data-value') as string\n\n if (this.multiple) {\n const values = this.value instanceof Array ? this.value : typeof this.value == 'string' ? [this.value] : []\n\n const idx = (this.value || []).indexOf(value)\n if (idx != -1) {\n values.splice(idx, 1)\n } else {\n values.push(value)\n }\n this.value = [...values]\n } else {\n this.value = this.value === value ? undefined : value\n }\n\n this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true, detail: this.value }))\n }\n}\n"]}
@@ -39,5 +39,65 @@ describe('ox-input-select-buttons', () => {
39
39
  await el.updateComplete;
40
40
  chips(el).forEach(chip => expect(getComputedStyle(chip).textTransform).to.equal('none'));
41
41
  });
42
+ /*
43
+ * A chip may carry how many rows it stands for — the stages of a list with the number in each. The number shows
44
+ * after the name whether the chip is pressed or not, and a chip without one shows its name alone as before.
45
+ */
46
+ it('shows each chip\'s count after its name, pressed or not', async () => {
47
+ const el = await fixture(html `
48
+ <ox-input-select-buttons
49
+ multiple
50
+ .value=${['lead']}
51
+ .options=${[
52
+ { display: 'Lead', value: 'lead', count: 3 },
53
+ { display: 'Won', value: 'won', count: 0 },
54
+ { display: 'Plain', value: 'plain' }
55
+ ]}
56
+ ></ox-input-select-buttons>
57
+ `);
58
+ const [lead, won, plain] = chips(el);
59
+ expect(lead.selected).to.equal(true);
60
+ expect(won.selected).to.equal(false);
61
+ expect(lead.querySelector('.count')?.textContent).to.equal('3');
62
+ expect(won.querySelector('.count')?.textContent).to.equal('0');
63
+ expect(lead.textContent.trim()).to.equal('Lead3');
64
+ expect(plain.querySelector('.count')).to.equal(null);
65
+ expect(plain.label).to.equal('Plain');
66
+ });
67
+ it('toggles a counted chip like any other, keeping the rest pressed', async () => {
68
+ const el = (await fixture(html `
69
+ <ox-input-select-buttons
70
+ multiple
71
+ .value=${['lead', 'won']}
72
+ .options=${[
73
+ { display: 'Lead', value: 'lead', count: 3 },
74
+ { display: 'Won', value: 'won', count: 1 }
75
+ ]}
76
+ ></ox-input-select-buttons>
77
+ `));
78
+ chips(el)[1].click();
79
+ expect(el.value).to.deep.equal(['lead']);
80
+ chips(el)[1].click();
81
+ expect(el.value).to.deep.equal(['lead', 'won']);
82
+ });
83
+ /* A pressed chip is told by its fill, not a checkmark: it keeps its width, so the row does not shift as chips toggle. */
84
+ it('marks a pressed chip without a checkmark, at the same width as when not pressed', async () => {
85
+ const el = await fixture(html `
86
+ <ox-input-select-buttons
87
+ multiple
88
+ .value=${['a']}
89
+ .options=${[
90
+ { display: 'Same', value: 'a', count: 12 },
91
+ { display: 'Same', value: 'b', count: 12 }
92
+ ]}
93
+ ></ox-input-select-buttons>
94
+ `);
95
+ const [pressed, released] = chips(el);
96
+ await pressed.updateComplete;
97
+ expect(pressed.selected).to.equal(true);
98
+ const check = pressed.shadowRoot.querySelector('svg.checkmark');
99
+ expect(!check || check.getBoundingClientRect().width === 0).to.equal(true);
100
+ expect(pressed.getBoundingClientRect().width).to.equal(released.getBoundingClientRect().width);
101
+ });
42
102
  });
43
103
  //# sourceMappingURL=ox-input-select-buttons.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ox-input-select-buttons.test.js","sourceRoot":"","sources":["../../test/ox-input-select-buttons.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,CAAA;AAE1B,OAAO,mCAAmC,CAAA;AAE1C;;;;;;GAMG;AACH,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;IACvC,MAAM,OAAO,GAAG;QACd,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE;QACpC,EAAE,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,cAAc,EAAE;KACnD,CAAA;IAED,MAAM,KAAK,GAAG,CAAC,EAAO,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,CAAkB,CAAA;IAEjG,EAAE,CAAC,wCAAwC,EAAE,KAAK,IAAI,EAAE;QACtD,MAAM,EAAE,GAAG,MAAM,OAAO,CAAC,IAAI,CAAA,qCAAqC,OAAO,6BAA6B,CAAC,CAAA;QAEvG,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;QACnC,KAAK,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAA;IAChG,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,wEAAwE,EAAE,KAAK,IAAI,EAAE;QACtF,MAAM,EAAE,GAAG,MAAM,OAAO,CAAC,IAAI,CAAA;;;mBAGd,OAAO;;KAErB,CAAC,CAAA;QAEF,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;QACnC,KAAK,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAA;IAC1F,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,mEAAmE,EAAE,KAAK,IAAI,EAAE;QACjF,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,IAAI,CAAA;;4CAES,OAAO;;KAE9C,CAAC,CAAA;QACF,MAAM,EAAE,GAAG,IAAI,CAAC,aAAa,CAAC,yBAAyB,CAAQ,CAAA;QAC/D,MAAM,EAAE,CAAC,cAAc,CAAA;QAEvB,KAAK,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAA;IAC1F,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA","sourcesContent":["import { expect, fixture } from '@open-wc/testing'\nimport { html } from 'lit'\n\nimport '../src/ox-input-select-buttons.js'\n\n/**\n * Chip labels.\n *\n * Most screens hand the chips words (`important`, `due`) and keep them capitalized. Some hand them\n * identifiers — a part name `roller-row-1`, a code — and those must show as written. The caller says\n * so with --ox-input-select-buttons-label-text-transform; a screen that sets nothing keeps capitalize.\n */\ndescribe('ox-input-select-buttons', () => {\n const options = [\n { display: 'frame', value: 'frame' },\n { display: 'roller-row-1', value: 'roller-row-1' }\n ]\n\n const chips = (el: any) => [...el.renderRoot.querySelectorAll('md-filter-chip')] as HTMLElement[]\n\n it('capitalizes the chip labels by default', async () => {\n const el = await fixture(html`<ox-input-select-buttons .options=${options}></ox-input-select-buttons>`)\n\n expect(chips(el)).to.have.length(2)\n chips(el).forEach(chip => expect(getComputedStyle(chip).textTransform).to.equal('capitalize'))\n })\n\n it('shows the labels as written when the caller sets the transform to none', async () => {\n const el = await fixture(html`\n <ox-input-select-buttons\n style=\"--ox-input-select-buttons-label-text-transform: none\"\n .options=${options}\n ></ox-input-select-buttons>\n `)\n\n expect(chips(el)).to.have.length(2)\n chips(el).forEach(chip => expect(getComputedStyle(chip).textTransform).to.equal('none'))\n })\n\n it('takes the transform from an ancestor, so a dialog can set it once', async () => {\n const host = await fixture(html`\n <div style=\"--ox-input-select-buttons-label-text-transform: none\">\n <ox-input-select-buttons .options=${options}></ox-input-select-buttons>\n </div>\n `)\n const el = host.querySelector('ox-input-select-buttons') as any\n await el.updateComplete\n\n chips(el).forEach(chip => expect(getComputedStyle(chip).textTransform).to.equal('none'))\n })\n})\n"]}
1
+ {"version":3,"file":"ox-input-select-buttons.test.js","sourceRoot":"","sources":["../../test/ox-input-select-buttons.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { expect, fixture } from '@open-wc/testing'\nimport { html } from 'lit'\n\nimport '../src/ox-input-select-buttons.js'\n\n/**\n * Chip labels.\n *\n * Most screens hand the chips words (`important`, `due`) and keep them capitalized. Some hand them\n * identifiers — a part name `roller-row-1`, a code — and those must show as written. The caller says\n * so with --ox-input-select-buttons-label-text-transform; a screen that sets nothing keeps capitalize.\n */\ndescribe('ox-input-select-buttons', () => {\n const options = [\n { display: 'frame', value: 'frame' },\n { display: 'roller-row-1', value: 'roller-row-1' }\n ]\n\n const chips = (el: any) => [...el.renderRoot.querySelectorAll('md-filter-chip')] as HTMLElement[]\n\n it('capitalizes the chip labels by default', async () => {\n const el = await fixture(html`<ox-input-select-buttons .options=${options}></ox-input-select-buttons>`)\n\n expect(chips(el)).to.have.length(2)\n chips(el).forEach(chip => expect(getComputedStyle(chip).textTransform).to.equal('capitalize'))\n })\n\n it('shows the labels as written when the caller sets the transform to none', async () => {\n const el = await fixture(html`\n <ox-input-select-buttons\n style=\"--ox-input-select-buttons-label-text-transform: none\"\n .options=${options}\n ></ox-input-select-buttons>\n `)\n\n expect(chips(el)).to.have.length(2)\n chips(el).forEach(chip => expect(getComputedStyle(chip).textTransform).to.equal('none'))\n })\n\n it('takes the transform from an ancestor, so a dialog can set it once', async () => {\n const host = await fixture(html`\n <div style=\"--ox-input-select-buttons-label-text-transform: none\">\n <ox-input-select-buttons .options=${options}></ox-input-select-buttons>\n </div>\n `)\n const el = host.querySelector('ox-input-select-buttons') as any\n await el.updateComplete\n\n chips(el).forEach(chip => expect(getComputedStyle(chip).textTransform).to.equal('none'))\n })\n\n /*\n * A chip may carry how many rows it stands for — the stages of a list with the number in each. The number shows\n * after the name whether the chip is pressed or not, and a chip without one shows its name alone as before.\n */\n it('shows each chip\\'s count after its name, pressed or not', async () => {\n const el = await fixture(html`\n <ox-input-select-buttons\n multiple\n .value=${['lead']}\n .options=${[\n { display: 'Lead', value: 'lead', count: 3 },\n { display: 'Won', value: 'won', count: 0 },\n { display: 'Plain', value: 'plain' }\n ]}\n ></ox-input-select-buttons>\n `)\n const [lead, won, plain] = chips(el) as any[]\n\n expect(lead.selected).to.equal(true)\n expect(won.selected).to.equal(false)\n expect(lead.querySelector('.count')?.textContent).to.equal('3')\n expect(won.querySelector('.count')?.textContent).to.equal('0')\n expect(lead.textContent.trim()).to.equal('Lead3')\n expect(plain.querySelector('.count')).to.equal(null)\n expect(plain.label).to.equal('Plain')\n })\n\n it('toggles a counted chip like any other, keeping the rest pressed', async () => {\n const el = (await fixture(html`\n <ox-input-select-buttons\n multiple\n .value=${['lead', 'won']}\n .options=${[\n { display: 'Lead', value: 'lead', count: 3 },\n { display: 'Won', value: 'won', count: 1 }\n ]}\n ></ox-input-select-buttons>\n `)) as any\n chips(el)[1].click()\n expect(el.value).to.deep.equal(['lead'])\n chips(el)[1].click()\n expect(el.value).to.deep.equal(['lead', 'won'])\n })\n\n /* A pressed chip is told by its fill, not a checkmark: it keeps its width, so the row does not shift as chips toggle. */\n it('marks a pressed chip without a checkmark, at the same width as when not pressed', async () => {\n const el = await fixture(html`\n <ox-input-select-buttons\n multiple\n .value=${['a']}\n .options=${[\n { display: 'Same', value: 'a', count: 12 },\n { display: 'Same', value: 'b', count: 12 }\n ]}\n ></ox-input-select-buttons>\n `)\n const [pressed, released] = chips(el) as any[]\n await pressed.updateComplete\n\n expect(pressed.selected).to.equal(true)\n const check = pressed.shadowRoot.querySelector('svg.checkmark')\n expect(!check || check.getBoundingClientRect().width === 0).to.equal(true)\n expect(pressed.getBoundingClientRect().width).to.equal(released.getBoundingClientRect().width)\n })\n})\n"]}