@operato/form 8.0.0-beta.0 → 8.0.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/package.json +7 -7
  3. package/.editorconfig +0 -29
  4. package/.storybook/main.js +0 -3
  5. package/.storybook/preview.js +0 -52
  6. package/.storybook/server.mjs +0 -8
  7. package/demo/index.html +0 -110
  8. package/src/components/ox-custom-input.ts +0 -102
  9. package/src/components/ox-custom-select.ts +0 -91
  10. package/src/components/ox-file-uploader.ts +0 -164
  11. package/src/components/ox-form-master.ts +0 -246
  12. package/src/components/ox-form-paginator.ts +0 -60
  13. package/src/components/ox-search-form-paginator.ts +0 -46
  14. package/src/components/ox-search-form.ts +0 -467
  15. package/src/filters/filter-checkbox.ts +0 -34
  16. package/src/filters/filter-input-barcode.ts +0 -35
  17. package/src/filters/filter-input.ts +0 -30
  18. package/src/filters/filter-range-date.ts +0 -81
  19. package/src/filters/filter-range-number.ts +0 -64
  20. package/src/filters/filter-select.ts +0 -56
  21. package/src/filters/filter-styles.ts +0 -127
  22. package/src/filters/index.ts +0 -10
  23. package/src/filters/ox-filter-personalizer.ts +0 -188
  24. package/src/filters/ox-filters-form-base.ts +0 -437
  25. package/src/filters/registry.ts +0 -54
  26. package/src/index.ts +0 -4
  27. package/src/styles/index.ts +0 -3
  28. package/src/styles/multi-column-form-styles.ts +0 -192
  29. package/src/styles/search-form-styles.ts +0 -160
  30. package/src/styles/single-column-form-styles.ts +0 -114
  31. package/src/types.ts +0 -106
  32. package/stories/ox-filters-form-barcode.stories.ts +0 -140
  33. package/stories/ox-filters-form-base-bounded.stories.ts +0 -208
  34. package/stories/ox-filters-form-base-change-handler.stories.ts +0 -220
  35. package/stories/ox-filters-form-base-page-preference.stories.ts +0 -177
  36. package/stories/ox-filters-form-base.stories.ts +0 -179
  37. package/stories/ox-search-form-change-handler.stories.ts +0 -253
  38. package/stories/ox-search-form.stories.ts +0 -258
  39. package/tsconfig.json +0 -24
  40. package/web-dev-server.config.mjs +0 -27
  41. package/web-test-runner.config.mjs +0 -41
@@ -1,64 +0,0 @@
1
- import { html } from 'lit-html'
2
-
3
- import { FilterSelectRenderer } from '../types.js'
4
-
5
- export const FilterRangeNumber: FilterSelectRenderer = (filter, value, owner) => {
6
- const { name, operator, readonly } = filter
7
- const [from, to] = value instanceof Array ? value : []
8
-
9
- return html`
10
- <input
11
- name=${name}
12
- type="number"
13
- placeholder="minimum"
14
- .value=${from}
15
- from
16
- @keyup=${(e: KeyboardEvent) => {
17
- if (e.key !== 'Enter') {
18
- return
19
- }
20
- ;(e.target as HTMLElement).dispatchEvent(
21
- new CustomEvent('filter-change', {
22
- bubbles: true,
23
- composed: true,
24
- detail: {
25
- name,
26
- operator,
27
- value: Array.from(
28
- (e.target as HTMLElement).parentElement!.querySelectorAll('input[from], input[to]')
29
- ).map(input => (input as HTMLInputElement).value)
30
- }
31
- })
32
- )
33
- }}
34
- ?readonly=${readonly}
35
- />
36
- ~
37
- <input
38
- name=${name}
39
- type="number"
40
- placeholder="maximum"
41
- .value=${to}
42
- to
43
- @keyup=${(e: KeyboardEvent) => {
44
- if (e.key !== 'Enter') {
45
- return
46
- }
47
- ;(e.target as HTMLElement).dispatchEvent(
48
- new CustomEvent('filter-change', {
49
- bubbles: true,
50
- composed: true,
51
- detail: {
52
- name,
53
- operator,
54
- value: Array.from(
55
- (e.target as HTMLElement).parentElement!.querySelectorAll('input[from], input[to]')
56
- ).map(input => (input as HTMLInputElement).value)
57
- }
58
- })
59
- )
60
- }}
61
- ?readonly=${readonly}
62
- />
63
- `
64
- }
@@ -1,56 +0,0 @@
1
- import '@operato/input/ox-checkbox.js'
2
-
3
- import { html } from 'lit'
4
- import { until } from 'lit/directives/until.js'
5
-
6
- import { FilterOperator, FilterSelectRenderer, SelectOption, SelectOptionObject } from '../types.js'
7
-
8
- function buildOptions(options: SelectOption[], operator?: FilterOperator) {
9
- const selectOptionObjects = options.map(option => {
10
- switch (typeof option) {
11
- case 'string':
12
- return {
13
- display: option,
14
- value: option
15
- }
16
- case 'object':
17
- return {
18
- display: option.display || option.name,
19
- value: option.value
20
- }
21
- default:
22
- return option
23
- }
24
- }) as SelectOptionObject[]
25
-
26
- return operator === 'in'
27
- ? html`
28
- ${selectOptionObjects
29
- ?.filter(option => !!option)
30
- .map(
31
- ({ value, display, name }) => html` <ox-checkbox option value=${value}>${display || name}</ox-checkbox> `
32
- )}
33
- `
34
- : html`
35
- ${selectOptionObjects?.map(
36
- ({ value, display, name }) => html` <div option value=${value}>${display || name}&nbsp;</div> `
37
- )}
38
- `
39
- }
40
-
41
- export const FilterSelect: FilterSelectRenderer = (filter, value, owner) => {
42
- /* value는 filters-form이나 grid-header에서 처리되므로 이 곳에서는 무시한다. */
43
- var { operator, options } = filter
44
-
45
- if (typeof options === 'function') {
46
- options = (options as Function).call(filter, owner)
47
-
48
- if (options instanceof Promise) {
49
- return html`${until(options.then(options => buildOptions(options, operator)))}`
50
- } else {
51
- return buildOptions((options || []) as SelectOption[], operator)
52
- }
53
- } else {
54
- return buildOptions((options || []) as SelectOption[], operator)
55
- }
56
- }
@@ -1,127 +0,0 @@
1
- import { css } from 'lit'
2
-
3
- export const FilterStyles = css`
4
- :host {
5
- --ox-filters-input-placeholder-color: var(--input-placeholder-color, var(--md-sys-color-on-surface-variant));
6
-
7
- --ox-filters-input-border: var(--input-border, 1px solid var(--md-sys-color-outline));
8
- --ox-filters-input-focus-border: var(--input-focus-border, 1px solid var(--md-sys-color-primary));
9
- --ox-filters-input-font: var(--input-font, normal 14px var(--theme-font));
10
- --ox-filters-input-color: var(--input-color, var(--md-sys-color-on-surface));
11
- --ox-filters-input-focus-color: var(--input-focus-color, var(--md-sys-color-on-surface-variant));
12
- --ox-filters-label-font: var(--label-font, normal 14px var(--theme-font));
13
- --ox-filters-label-color: var(--label-color, var(--md-sys-color-on-surface));
14
- --ox-filters-input-background-color: transparent;
15
-
16
- --ox-filters-form-gap: var(--input-gap-vertical, 8px) var(--input-gap-horizontal, 16px);
17
- --ox-filters-input-padding: 0 var(--spacing-small);
18
-
19
- --ox-select-padding: var(--ox-filters-input-padding);
20
- --ox-checkbox-background-color: var(--ox-filters-input-background-color, transparent);
21
-
22
- --md-sys-color-on-primary: transparent;
23
- --form-element-height-medium: var(--form-element-height-small);
24
- }
25
-
26
- label {
27
- font-size: var(--md-sys-typescale-label-large-size, 0.875rem);
28
- color: var(--md-sys-color-primary);
29
- }
30
-
31
- span {
32
- text-transform: capitalize;
33
- }
34
-
35
- input::placeholder {
36
- color: var(--ox-filters-input-placeholder-color, var(--md-sys-color-on-surface-variant));
37
- opacity: 0.7;
38
- }
39
-
40
- input,
41
- ox-input-search,
42
- [filter-input] {
43
- padding: var(--ox-filters-input-padding);
44
- height: var(--form-element-height-medium);
45
- }
46
-
47
- ox-select,
48
- ox-input-search,
49
- input,
50
- [filter-input] {
51
- border: none;
52
- border-bottom: var(--ox-filters-input-border, var(--md-sys-color-outline));
53
- font: var(--ox-filters-input-font);
54
- color: var(--ox-filters-input-color, var(--md-sys-color-on-surface-variant));
55
- background-color: var(--ox-filters-input-background-color, transparent);
56
- vertical-align: middle;
57
- }
58
-
59
- ox-select:focus,
60
- input:focus,
61
- [filter-input]:focus {
62
- outline: none;
63
- border-bottom: var(--ox-filters-input-focus-border);
64
- color: var(--ox-filters-input-focus-color, var(--md-sys-color-primary));
65
- }
66
-
67
- ox-select {
68
- min-width: 90px;
69
- max-width: 170px;
70
- }
71
-
72
- ox-input-search {
73
- max-width: 150px;
74
- }
75
-
76
- input[type='number'] {
77
- max-width: 90px;
78
- }
79
-
80
- input[type*='date'],
81
- input[type*='time'],
82
- input[type='week'],
83
- input[type='month'] {
84
- max-width: 170px;
85
- }
86
-
87
- [filter-input] {
88
- min-width: 140px;
89
- max-width: 170px;
90
- }
91
-
92
- @media only screen and (max-width: 460px) {
93
- :host {
94
- --ox-filters-form-label-font: bold 13px var(--theme-font);
95
- --ox-filters-input-font: normal 16px var(--theme-font);
96
- }
97
-
98
- ox-input-barcode {
99
- max-width: unset;
100
- flex: 1;
101
- }
102
-
103
- ox-input-search {
104
- max-width: unset;
105
- }
106
-
107
- ox-select {
108
- max-width: unset;
109
- }
110
-
111
- ox-checkbox {
112
- max-width: unset;
113
- }
114
-
115
- input[type='number'] {
116
- max-width: unset;
117
- }
118
-
119
- input {
120
- flex: 1;
121
- }
122
-
123
- [readonly] {
124
- background-color: #f0f0f0;
125
- }
126
- }
127
- `
@@ -1,10 +0,0 @@
1
- export * from './registry.js'
2
-
3
- export * from './filter-select.js'
4
- export * from './filter-input.js'
5
- export * from './filter-checkbox.js'
6
- export * from './filter-range-date.js'
7
- export * from './filter-range-number.js'
8
-
9
- export * from './ox-filters-form-base.js'
10
- export * from '../types.js'
@@ -1,188 +0,0 @@
1
- import '@material/web/button/outlined-button.js'
2
-
3
- import { css, html, LitElement } from 'lit'
4
- import { customElement, property, state } from 'lit/decorators.js'
5
- import { ifDefined } from 'lit/directives/if-defined.js'
6
-
7
- import { i18next } from '@operato/i18n'
8
- import { OxPopupList } from '@operato/popup'
9
-
10
- import { FilterConfig, PersonalFilterPreference } from '../types.js'
11
-
12
- import { OxFiltersFormBase } from './ox-filters-form-base'
13
- import { OxCheckbox } from '@operato/input'
14
-
15
- @customElement('ox-filter-personalizer')
16
- export class OxFilterPersonalizer extends LitElement {
17
- static styles = [
18
- css`
19
- md-icon {
20
- --md-icon-size: 16px;
21
- width: 36px;
22
- height: 36px;
23
- color: var(--md-sys-color-secondary-container);
24
- cursor: pointer;
25
-
26
- display: flex;
27
- place-content: center;
28
- place-items: center;
29
- position: relative;
30
-
31
- &:hover {
32
- color: var(--md-sys-color-primary-container);
33
- }
34
- }
35
-
36
- md-ripple {
37
- border-radius: 50%;
38
- inset: unset;
39
- height: 36px;
40
- width: 36px;
41
- }
42
- `
43
- ]
44
-
45
- @property({ type: Boolean, attribute: true }) debug: boolean = false
46
-
47
- @state() private preference?: PersonalFilterPreference
48
-
49
- render() {
50
- return html`
51
- <md-icon
52
- @click=${async (e: MouseEvent) => {
53
- const form = this.closest('ox-filters-form-base') as OxFiltersFormBase
54
- const { filters, personalFilters = [] } = form
55
- const queryFilters = await form.getQueryFilters()
56
-
57
- this.preference = {
58
- filters: (
59
- personalFilters.map(filter => {
60
- const originFilter = filters.find(f => f.name == filter.name)
61
-
62
- if (!originFilter) {
63
- /* 원래 filters 설정에 있는 것들 만을 유지한다. */
64
- return
65
- }
66
-
67
- return {
68
- name: filter.name,
69
- hidden: filter.hidden,
70
- /* 만약, filters에 기본값이 이미 설정되어 있다면, 그대로 유지한다. */
71
- value: originFilter!.value ?? queryFilters.find(f => f.name == filter.name)?.value
72
- }
73
- }) || []
74
- ).filter(Boolean) as Partial<FilterConfig>[]
75
- }
76
-
77
- const template = html`
78
- <div class="personalizer-header" slot="header">
79
- <md-icon
80
- style="margin-left: auto;"
81
- @click=${async (e: MouseEvent) => {
82
- if (form.personalConfigProvider) {
83
- form.personalConfig = await form.personalConfigProvider.save(this.preference)
84
- }
85
- popup.close()
86
- }}
87
- title=${String(i18next.t('button.save'))}
88
- >keep</md-icon
89
- ><md-icon
90
- @click=${async (e: MouseEvent) => {
91
- if (form.personalConfigProvider) {
92
- form.personalConfig = this.preference = {}
93
- await form.personalConfigProvider.reset()
94
- }
95
- popup.close()
96
- }}
97
- title=${String(i18next.t('button.delete'))}
98
- >keep_off</md-icon
99
- ><md-icon @click=${async (e: MouseEvent) => popup.close()} title=${String(i18next.t('button.close'))}
100
- >close</md-icon
101
- >
102
- </div>
103
-
104
- ${this.preference?.filters!.map(
105
- filter => html`
106
- <ox-checkbox label="checkbox" ?checked=${!filter.hidden} value=${ifDefined(filter.name)} option
107
- >${filter.name}<span style="position: absolute; right: 10px; cursor: move;" handle
108
- >☰</span
109
- ></ox-checkbox
110
- >
111
- `
112
- )}
113
- `
114
-
115
- const popup = OxPopupList.open({
116
- template,
117
- multiple: true,
118
- sortable: true,
119
- debug: this.debug,
120
- attrSelected: 'checked',
121
- top: e.pageY,
122
- left: e.pageX,
123
- styles: css`
124
- :host {
125
- width: 240px;
126
- max-height: 300px;
127
- overflow: auto;
128
- }
129
-
130
- ::slotted(.personalizer-header) {
131
- --md-icon-size: 1.4em;
132
-
133
- display: flex;
134
- flex-direction: row;
135
- align-items: center;
136
- text-transform: capitalize;
137
- box-shadow: 0 3px 3px rgba(0, 0, 0, 0.3);
138
- }
139
-
140
- ::slotted([option]) {
141
- position: relative;
142
- user-select: none;
143
- }
144
- `
145
- })
146
-
147
- popup.onselect = (e: Event) => {
148
- const selected = (e as CustomEvent).detail
149
-
150
- const pconfig: PersonalFilterPreference = { ...form.personalConfig }
151
- const pfilters = this.preference?.filters || form.filters
152
-
153
- pconfig.filters = pfilters.map(filter => {
154
- return {
155
- name: filter.name,
156
- hidden: selected.indexOf(filter.name) == -1,
157
- value: filter.value
158
- }
159
- })
160
-
161
- form.personalConfig = this.preference = pconfig
162
-
163
- form.applyUpdatedConfiguration()
164
- }
165
-
166
- popup.addEventListener('sorted', (e: Event) => {
167
- const sorted = (e as CustomEvent).detail as HTMLElement[]
168
-
169
- const pconfig: PersonalFilterPreference = { ...form.personalConfig }
170
- const pfilters = this.preference?.filters || form.filters
171
-
172
- pconfig.filters = sorted
173
- .map(element => {
174
- const name = (element as OxCheckbox).value
175
- return pfilters.find(filter => filter.name == name)!
176
- })
177
- .filter(Boolean)
178
-
179
- form.personalConfig = this.preference = pconfig
180
-
181
- form.applyUpdatedConfiguration()
182
- })
183
- }}
184
- >settings<md-ripple></md-ripple
185
- ></md-icon>
186
- `
187
- }
188
- }