@operato/input 10.29.39 → 10.29.41
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 +18 -0
- package/coverage/lcov-report/index.html +139 -139
- package/coverage/lcov-report/webpack/bootstrap.html +1 -1
- package/coverage/lcov-report/webpack/index.html +1 -1
- package/coverage/lcov-report/webpack/runtime/define property getters.html +1 -1
- package/coverage/lcov-report/webpack/runtime/global.html +1 -1
- package/coverage/lcov-report/webpack/runtime/hasOwnProperty shorthand.html +1 -1
- package/coverage/lcov-report/webpack/runtime/index.html +1 -1
- package/coverage/lcov-report/webpack/runtime/make namespace object.html +1 -1
- package/coverage/lcov.info +16621 -16463
- package/dist/src/ox-input-select-buttons.js +2 -1
- package/dist/src/ox-input-select-buttons.js.map +1 -1
- package/dist/src/ox-select.d.ts +2 -0
- package/dist/src/ox-select.js +8 -0
- package/dist/src/ox-select.js.map +1 -1
- package/dist/test/ox-input-select-buttons.test.d.ts +1 -0
- package/dist/test/ox-input-select-buttons.test.js +43 -0
- package/dist/test/ox-input-select-buttons.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/test/ox-input-select-buttons.test.ts +51 -0
|
@@ -33,8 +33,9 @@ let OxInputSelectButtons = class OxInputSelectButtons extends OxFormField {
|
|
|
33
33
|
* md 칩을 갈아치우지 않고 그 토큰으로만 조정한다. 이 컴포넌트를 쓰는 화면이 많고, 자기 것으로
|
|
34
34
|
* 다시 만들면 그 화면들이 두 모양으로 갈린다.
|
|
35
35
|
*/
|
|
36
|
+
/* Labels that are identifiers (part names, codes) must show as written: set this to none. */
|
|
36
37
|
md-filter-chip {
|
|
37
|
-
text-transform: capitalize;
|
|
38
|
+
text-transform: var(--ox-input-select-buttons-label-text-transform, capitalize);
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
:host {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ox-input-select-buttons.js","sourceRoot":"","sources":["../../src/ox-input-select-buttons.ts"],"names":[],"mappings":"AAAA;;GAEG;;AAEH,OAAO,oCAAoC,CAAA;AAC3C,OAAO,iCAAiC,CAAA;AAExC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAA;AAC/B,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAA;AAExD,OAAO,EAAE,uCAAuC,EAAE,sBAAsB,EAAE,MAAM,yCAAyC,CAAA;AAEzH,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAiBxC,IAAM,oBAAoB,GAA1B,MAAM,oBAAqB,SAAQ,WAAW;IAA9C;;
|
|
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"]}
|
package/dist/src/ox-select.d.ts
CHANGED
|
@@ -18,6 +18,8 @@ export declare class OxSelect extends OxFormField {
|
|
|
18
18
|
connectedCallback(): void;
|
|
19
19
|
disconnectedCallback(): void;
|
|
20
20
|
handleKeyDown(e: KeyboardEvent): void;
|
|
21
|
+
/** Its list's options arrived or changed: show the label of the value they now hold. */
|
|
22
|
+
private optionsChanged;
|
|
21
23
|
updated(changes: PropertyValues<this>): Promise<void>;
|
|
22
24
|
setOptions(options: string[] | {
|
|
23
25
|
display: string;
|
package/dist/src/ox-select.js
CHANGED
|
@@ -19,6 +19,12 @@ let OxSelect = class OxSelect extends OxFormField {
|
|
|
19
19
|
this.popupContainer = null;
|
|
20
20
|
this.observer = null;
|
|
21
21
|
this.hasLabelSlot = false;
|
|
22
|
+
/** Its list's options arrived or changed: show the label of the value they now hold. */
|
|
23
|
+
this.optionsChanged = (e) => {
|
|
24
|
+
e.stopPropagation();
|
|
25
|
+
const popupList = e.target;
|
|
26
|
+
this.label = popupList.getSelectedLabels();
|
|
27
|
+
};
|
|
22
28
|
}
|
|
23
29
|
static { this.styles = [
|
|
24
30
|
InputStyles,
|
|
@@ -97,11 +103,13 @@ let OxSelect = class OxSelect extends OxFormField {
|
|
|
97
103
|
this.setAttribute('tabindex', '0');
|
|
98
104
|
this.addEventListener('keydown', this.handleKeyDown);
|
|
99
105
|
this.addEventListener('click', this.expand);
|
|
106
|
+
this.addEventListener('options-change', this.optionsChanged);
|
|
100
107
|
}
|
|
101
108
|
disconnectedCallback() {
|
|
102
109
|
super.disconnectedCallback();
|
|
103
110
|
this.removeEventListener('keydown', this.handleKeyDown);
|
|
104
111
|
this.removeEventListener('click', this.expand);
|
|
112
|
+
this.removeEventListener('options-change', this.optionsChanged);
|
|
105
113
|
}
|
|
106
114
|
handleKeyDown(e) {
|
|
107
115
|
e.preventDefault();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ox-select.js","sourceRoot":"","sources":["../../src/ox-select.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @license Copyright © HatioLab Inc. All rights reserved.\n */\n\nimport '@material/web/icon/icon.js'\nimport '@operato/popup/ox-popup-list.js'\nimport './ox-checkbox.js'\n\nimport { css, html, render, PropertyValues } from 'lit'\nimport { customElement, property, query, state } from 'lit/decorators.js'\n\nimport { OxPopupList } from '@operato/popup'\n\nimport { OxFormField } from './ox-form-field.js'\nimport { InputStyles } from './input-styles.js'\n\n@customElement('ox-select')\nexport class OxSelect extends OxFormField {\n static styles = [\n InputStyles,\n css`\n /* 컴포넌트 조정 지점(L3) — 모두 L2 계약(--ox-input-*)으로 폴백하므로\n 앱은 전역(L2) 또는 이 컴포넌트만(L3) 어느 쪽으로도 통제할 수 있다.\n 고정 리터럴을 남기지 않는다. */\n :host {\n display: block;\n position: relative;\n border-bottom: var(--ox-select-border-bottom, var(--ox-input-underline));\n\n --ox-select-padding: var(--ox-input-padding);\n --ox-select-font: var(--ox-input-font);\n --ox-select-color: var(--ox-input-color);\n --ox-select-icon-color: var(--ox-input-placeholder-color);\n --ox-select-icon-hover-color: var(--ox-input-focus-color);\n --ox-select-icon-size: var(--ox-input-font-size);\n --ox-select-icon-opacity: 0.7;\n }\n\n div {\n width: 100%;\n\n display: flex;\n flex-direction: row;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n padding: var(--ox-select-padding);\n font: var(--ox-select-font);\n color: var(--ox-select-color);\n transition: var(--ox-input-transition);\n }\n\n span {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n gap: var(--ox-input-gap);\n }\n\n md-icon {\n --md-icon-size: var(--ox-select-icon-size);\n display: block;\n text-align: right;\n color: var(--ox-select-icon-color);\n opacity: var(--ox-select-icon-opacity);\n transition: var(--ox-input-transition);\n }\n\n div:hover md-icon {\n color: var(--ox-select-icon-hover-color);\n opacity: 1;\n }\n `\n ]\n\n @property({ type: String }) name: string = ''\n @property({ type: String }) placeholder: string = ''\n\n @state() label: string | string[] = ''\n @state() popupContainer: HTMLElement | null = null\n @state() observer: MutationObserver | null = null\n @state() hasLabelSlot: boolean = false\n\n render() {\n // value/label 은 문자열이 아닐 수 있다 (예: select option value 가 숫자 0/1).\n // `(0)?.trim()` 은 0 이 nullish 가 아니라 단락되지 않아 TypeError 가 난다 →\n // 비-문자열 스칼라는 String() 으로 강제, nullish 만 '' 처리.\n const asText = (v: unknown): string =>\n v instanceof Array ? v.join(', ') : typeof v === 'string' ? v.trim() : v == null ? '' : String(v)\n\n const label = asText(this.label) || asText(this.value) || this.placeholder || ''\n\n return html`\n <div @click=${this.expand}>\n <span data-reactive-tooltip> <slot name=\"label\">${label}</slot> </span>\n <md-icon>expand_more</md-icon>\n </div>\n\n <slot></slot>\n `\n }\n\n connectedCallback() {\n super.connectedCallback()\n\n this.setAttribute('tabindex', '0')\n this.addEventListener('keydown', this.handleKeyDown)\n this.addEventListener('click', this.expand)\n }\n\n disconnectedCallback() {\n super.disconnectedCallback()\n\n this.removeEventListener('keydown', this.handleKeyDown)\n this.removeEventListener('click', this.expand)\n }\n\n handleKeyDown(e: KeyboardEvent) {\n e.preventDefault()\n if (e.key === ' ' || e.key === 'Spacebar' || e.key === 'ArrowDown') {\n this.expand()\n }\n }\n\n async updated(changes: PropertyValues<this>) {\n if (changes.has('value')) {\n const popupList = (this.popupContainer?.querySelector('ox-popup-list') ||\n this.querySelector('ox-popup-list')) as OxPopupList\n\n if (popupList) {\n popupList.value = this.value\n await this.requestUpdate()\n this.label = popupList.getSelectedLabels()\n }\n }\n }\n\n setOptions(\n options: string[] | { display: string; value: string }[],\n opt: { multiple?: boolean; withSearch?: boolean } = {}\n ) {\n const objOptions = options.map(option => {\n return typeof option == 'string' ? { display: option, value: option } : option\n })\n\n const { multiple, withSearch } = opt || {}\n\n const template = html`\n <ox-popup-list\n align-left\n nowrap\n ?multiple=${multiple}\n attr-selected=${multiple ? 'checked' : ''}\n ?with-search=${withSearch}\n >\n ${multiple\n ? html`<ox-checkbox\n @change=${(e: Event) => {\n const target = e.target as HTMLInputElement\n const options = Array.from(target.parentElement!.querySelectorAll('[option]')).filter(\n option => !option.hasAttribute('hidden')\n )\n options.forEach(option => ((option as HTMLInputElement).checked = target.checked))\n\n this.value = options\n .map(option =>\n (option as HTMLInputElement).checked ? (option as HTMLInputElement).value : undefined\n )\n .filter(Boolean)\n }}\n >set all</ox-checkbox\n >\n ${objOptions.map(\n option => html` <ox-checkbox option value=${option.value}>${option.display}</ox-checkbox> `\n )}`\n : html`${objOptions.map(option => html` <div option value=${option.value}>${option.display}</div> `)}`}\n </ox-popup-list>\n `\n\n render(template, this)\n }\n\n expand() {\n if (this.disabled) {\n return\n }\n\n const slotContent = (this.renderRoot.querySelector('slot:not([name])') as HTMLSlotElement)?.assignedNodes() || []\n\n if (slotContent.length > 0) {\n const popupList = slotContent.find(content => content instanceof OxPopupList) as OxPopupList\n\n if (popupList) {\n const { left, bottom } = this.getBoundingClientRect()\n\n popupList.value = this.value\n popupList.style.width = `${this.offsetWidth}px`\n popupList.style.textWrap = 'nowrap'\n\n const selectHandler = async (e: Event) => {\n this.value = (e as CustomEvent).detail\n\n if (popupList) {\n await this.requestUpdate()\n this.label = popupList.getSelectedLabels()\n }\n }\n popupList.addEventListener('select', selectHandler)\n\n const closeHandler = (e: Event) => {\n /* popup이 close될 때 change 이벤트를 발생시킨다. */\n this.dispatchEvent(\n new CustomEvent('change', {\n bubbles: true,\n composed: true,\n detail: this.value\n })\n )\n popupList.removeEventListener('select', selectHandler)\n popupList.removeEventListener('close', closeHandler)\n\n this.appendChild(popupList)\n }\n popupList.addEventListener('close', closeHandler, { once: true })\n\n document.body.appendChild(popupList)\n\n popupList.open({\n left,\n top: bottom\n })\n }\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ox-select.js","sourceRoot":"","sources":["../../src/ox-select.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @license Copyright © HatioLab Inc. All rights reserved.\n */\n\nimport '@material/web/icon/icon.js'\nimport '@operato/popup/ox-popup-list.js'\nimport './ox-checkbox.js'\n\nimport { css, html, render, PropertyValues } from 'lit'\nimport { customElement, property, query, state } from 'lit/decorators.js'\n\nimport { OxPopupList } from '@operato/popup'\n\nimport { OxFormField } from './ox-form-field.js'\nimport { InputStyles } from './input-styles.js'\n\n@customElement('ox-select')\nexport class OxSelect extends OxFormField {\n static styles = [\n InputStyles,\n css`\n /* 컴포넌트 조정 지점(L3) — 모두 L2 계약(--ox-input-*)으로 폴백하므로\n 앱은 전역(L2) 또는 이 컴포넌트만(L3) 어느 쪽으로도 통제할 수 있다.\n 고정 리터럴을 남기지 않는다. */\n :host {\n display: block;\n position: relative;\n border-bottom: var(--ox-select-border-bottom, var(--ox-input-underline));\n\n --ox-select-padding: var(--ox-input-padding);\n --ox-select-font: var(--ox-input-font);\n --ox-select-color: var(--ox-input-color);\n --ox-select-icon-color: var(--ox-input-placeholder-color);\n --ox-select-icon-hover-color: var(--ox-input-focus-color);\n --ox-select-icon-size: var(--ox-input-font-size);\n --ox-select-icon-opacity: 0.7;\n }\n\n div {\n width: 100%;\n\n display: flex;\n flex-direction: row;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n padding: var(--ox-select-padding);\n font: var(--ox-select-font);\n color: var(--ox-select-color);\n transition: var(--ox-input-transition);\n }\n\n span {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n gap: var(--ox-input-gap);\n }\n\n md-icon {\n --md-icon-size: var(--ox-select-icon-size);\n display: block;\n text-align: right;\n color: var(--ox-select-icon-color);\n opacity: var(--ox-select-icon-opacity);\n transition: var(--ox-input-transition);\n }\n\n div:hover md-icon {\n color: var(--ox-select-icon-hover-color);\n opacity: 1;\n }\n `\n ]\n\n @property({ type: String }) name: string = ''\n @property({ type: String }) placeholder: string = ''\n\n @state() label: string | string[] = ''\n @state() popupContainer: HTMLElement | null = null\n @state() observer: MutationObserver | null = null\n @state() hasLabelSlot: boolean = false\n\n render() {\n // value/label 은 문자열이 아닐 수 있다 (예: select option value 가 숫자 0/1).\n // `(0)?.trim()` 은 0 이 nullish 가 아니라 단락되지 않아 TypeError 가 난다 →\n // 비-문자열 스칼라는 String() 으로 강제, nullish 만 '' 처리.\n const asText = (v: unknown): string =>\n v instanceof Array ? v.join(', ') : typeof v === 'string' ? v.trim() : v == null ? '' : String(v)\n\n const label = asText(this.label) || asText(this.value) || this.placeholder || ''\n\n return html`\n <div @click=${this.expand}>\n <span data-reactive-tooltip> <slot name=\"label\">${label}</slot> </span>\n <md-icon>expand_more</md-icon>\n </div>\n\n <slot></slot>\n `\n }\n\n connectedCallback() {\n super.connectedCallback()\n\n this.setAttribute('tabindex', '0')\n this.addEventListener('keydown', this.handleKeyDown)\n this.addEventListener('click', this.expand)\n this.addEventListener('options-change', this.optionsChanged)\n }\n\n disconnectedCallback() {\n super.disconnectedCallback()\n\n this.removeEventListener('keydown', this.handleKeyDown)\n this.removeEventListener('click', this.expand)\n this.removeEventListener('options-change', this.optionsChanged)\n }\n\n handleKeyDown(e: KeyboardEvent) {\n e.preventDefault()\n if (e.key === ' ' || e.key === 'Spacebar' || e.key === 'ArrowDown') {\n this.expand()\n }\n }\n\n /** Its list's options arrived or changed: show the label of the value they now hold. */\n private optionsChanged = (e: Event) => {\n e.stopPropagation()\n const popupList = e.target as OxPopupList\n this.label = popupList.getSelectedLabels()\n }\n\n async updated(changes: PropertyValues<this>) {\n if (changes.has('value')) {\n const popupList = (this.popupContainer?.querySelector('ox-popup-list') ||\n this.querySelector('ox-popup-list')) as OxPopupList\n\n if (popupList) {\n popupList.value = this.value\n await this.requestUpdate()\n this.label = popupList.getSelectedLabels()\n }\n }\n }\n\n setOptions(\n options: string[] | { display: string; value: string }[],\n opt: { multiple?: boolean; withSearch?: boolean } = {}\n ) {\n const objOptions = options.map(option => {\n return typeof option == 'string' ? { display: option, value: option } : option\n })\n\n const { multiple, withSearch } = opt || {}\n\n const template = html`\n <ox-popup-list\n align-left\n nowrap\n ?multiple=${multiple}\n attr-selected=${multiple ? 'checked' : ''}\n ?with-search=${withSearch}\n >\n ${multiple\n ? html`<ox-checkbox\n @change=${(e: Event) => {\n const target = e.target as HTMLInputElement\n const options = Array.from(target.parentElement!.querySelectorAll('[option]')).filter(\n option => !option.hasAttribute('hidden')\n )\n options.forEach(option => ((option as HTMLInputElement).checked = target.checked))\n\n this.value = options\n .map(option =>\n (option as HTMLInputElement).checked ? (option as HTMLInputElement).value : undefined\n )\n .filter(Boolean)\n }}\n >set all</ox-checkbox\n >\n ${objOptions.map(\n option => html` <ox-checkbox option value=${option.value}>${option.display}</ox-checkbox> `\n )}`\n : html`${objOptions.map(option => html` <div option value=${option.value}>${option.display}</div> `)}`}\n </ox-popup-list>\n `\n\n render(template, this)\n }\n\n expand() {\n if (this.disabled) {\n return\n }\n\n const slotContent = (this.renderRoot.querySelector('slot:not([name])') as HTMLSlotElement)?.assignedNodes() || []\n\n if (slotContent.length > 0) {\n const popupList = slotContent.find(content => content instanceof OxPopupList) as OxPopupList\n\n if (popupList) {\n const { left, bottom } = this.getBoundingClientRect()\n\n popupList.value = this.value\n popupList.style.width = `${this.offsetWidth}px`\n popupList.style.textWrap = 'nowrap'\n\n const selectHandler = async (e: Event) => {\n this.value = (e as CustomEvent).detail\n\n if (popupList) {\n await this.requestUpdate()\n this.label = popupList.getSelectedLabels()\n }\n }\n popupList.addEventListener('select', selectHandler)\n\n const closeHandler = (e: Event) => {\n /* popup이 close될 때 change 이벤트를 발생시킨다. */\n this.dispatchEvent(\n new CustomEvent('change', {\n bubbles: true,\n composed: true,\n detail: this.value\n })\n )\n popupList.removeEventListener('select', selectHandler)\n popupList.removeEventListener('close', closeHandler)\n\n this.appendChild(popupList)\n }\n popupList.addEventListener('close', closeHandler, { once: true })\n\n document.body.appendChild(popupList)\n\n popupList.open({\n left,\n top: bottom\n })\n }\n }\n }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import '../src/ox-input-select-buttons.js';
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { expect, fixture } from '@open-wc/testing';
|
|
2
|
+
import { html } from 'lit';
|
|
3
|
+
import '../src/ox-input-select-buttons.js';
|
|
4
|
+
/**
|
|
5
|
+
* Chip labels.
|
|
6
|
+
*
|
|
7
|
+
* Most screens hand the chips words (`important`, `due`) and keep them capitalized. Some hand them
|
|
8
|
+
* identifiers — a part name `roller-row-1`, a code — and those must show as written. The caller says
|
|
9
|
+
* so with --ox-input-select-buttons-label-text-transform; a screen that sets nothing keeps capitalize.
|
|
10
|
+
*/
|
|
11
|
+
describe('ox-input-select-buttons', () => {
|
|
12
|
+
const options = [
|
|
13
|
+
{ display: 'frame', value: 'frame' },
|
|
14
|
+
{ display: 'roller-row-1', value: 'roller-row-1' }
|
|
15
|
+
];
|
|
16
|
+
const chips = (el) => [...el.renderRoot.querySelectorAll('md-filter-chip')];
|
|
17
|
+
it('capitalizes the chip labels by default', async () => {
|
|
18
|
+
const el = await fixture(html `<ox-input-select-buttons .options=${options}></ox-input-select-buttons>`);
|
|
19
|
+
expect(chips(el)).to.have.length(2);
|
|
20
|
+
chips(el).forEach(chip => expect(getComputedStyle(chip).textTransform).to.equal('capitalize'));
|
|
21
|
+
});
|
|
22
|
+
it('shows the labels as written when the caller sets the transform to none', async () => {
|
|
23
|
+
const el = await fixture(html `
|
|
24
|
+
<ox-input-select-buttons
|
|
25
|
+
style="--ox-input-select-buttons-label-text-transform: none"
|
|
26
|
+
.options=${options}
|
|
27
|
+
></ox-input-select-buttons>
|
|
28
|
+
`);
|
|
29
|
+
expect(chips(el)).to.have.length(2);
|
|
30
|
+
chips(el).forEach(chip => expect(getComputedStyle(chip).textTransform).to.equal('none'));
|
|
31
|
+
});
|
|
32
|
+
it('takes the transform from an ancestor, so a dialog can set it once', async () => {
|
|
33
|
+
const host = await fixture(html `
|
|
34
|
+
<div style="--ox-input-select-buttons-label-text-transform: none">
|
|
35
|
+
<ox-input-select-buttons .options=${options}></ox-input-select-buttons>
|
|
36
|
+
</div>
|
|
37
|
+
`);
|
|
38
|
+
const el = host.querySelector('ox-input-select-buttons');
|
|
39
|
+
await el.updateComplete;
|
|
40
|
+
chips(el).forEach(chip => expect(getComputedStyle(chip).textTransform).to.equal('none'));
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
//# sourceMappingURL=ox-input-select-buttons.test.js.map
|
|
@@ -0,0 +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"]}
|