@operato/form 1.0.0-beta.4 → 1.0.0-beta.40

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 (62) hide show
  1. package/CHANGELOG.md +442 -0
  2. package/demo/index.html +68 -2
  3. package/dist/src/filters/filter-checkbox.d.ts +3 -0
  4. package/dist/src/filters/filter-checkbox.js +26 -0
  5. package/dist/src/filters/filter-checkbox.js.map +1 -0
  6. package/dist/src/filters/filter-input-barcode.d.ts +3 -0
  7. package/dist/src/filters/filter-input-barcode.js +27 -0
  8. package/dist/src/filters/filter-input-barcode.js.map +1 -0
  9. package/dist/src/filters/filter-input.d.ts +2 -0
  10. package/dist/src/filters/filter-input.js +24 -0
  11. package/dist/src/filters/filter-input.js.map +1 -0
  12. package/dist/src/filters/filter-range-date.d.ts +2 -0
  13. package/dist/src/filters/filter-range-date.js +54 -0
  14. package/dist/src/filters/filter-range-date.js.map +1 -0
  15. package/dist/src/filters/filter-range-number.d.ts +2 -0
  16. package/dist/src/filters/filter-range-number.js +53 -0
  17. package/dist/src/filters/filter-range-number.js.map +1 -0
  18. package/dist/src/filters/filter-select.d.ts +3 -0
  19. package/dist/src/filters/filter-select.js +33 -0
  20. package/dist/src/filters/filter-select.js.map +1 -0
  21. package/dist/src/filters/filter-styles.d.ts +1 -0
  22. package/dist/src/filters/filter-styles.js +88 -0
  23. package/dist/src/filters/filter-styles.js.map +1 -0
  24. package/dist/src/filters/index.d.ts +8 -0
  25. package/dist/src/filters/index.js +9 -0
  26. package/dist/src/filters/index.js.map +1 -0
  27. package/dist/src/filters/ox-filters-form-base.d.ts +25 -0
  28. package/dist/src/filters/ox-filters-form-base.js +238 -0
  29. package/dist/src/filters/ox-filters-form-base.js.map +1 -0
  30. package/dist/src/filters/registry.d.ts +7 -0
  31. package/dist/src/filters/registry.js +46 -0
  32. package/dist/src/filters/registry.js.map +1 -0
  33. package/dist/src/filters/types.d.ts +17 -0
  34. package/dist/src/filters/types.js +2 -0
  35. package/dist/src/filters/types.js.map +1 -0
  36. package/dist/src/index.d.ts +1 -0
  37. package/dist/src/index.js +1 -0
  38. package/dist/src/index.js.map +1 -1
  39. package/dist/stories/ox-filter-form-barcode.stories.d.ts +29 -0
  40. package/dist/stories/ox-filter-form-barcode.stories.js +82 -0
  41. package/dist/stories/ox-filter-form-barcode.stories.js.map +1 -0
  42. package/dist/stories/ox-filter-form-base.stories.d.ts +29 -0
  43. package/dist/stories/ox-filter-form-base.stories.js +82 -0
  44. package/dist/stories/ox-filter-form-base.stories.js.map +1 -0
  45. package/dist/tsconfig.tsbuildinfo +1 -1
  46. package/package.json +8 -6
  47. package/src/filters/filter-checkbox.ts +31 -0
  48. package/src/filters/filter-input-barcode.ts +33 -0
  49. package/src/filters/filter-input.ts +29 -0
  50. package/src/filters/filter-range-date.ts +64 -0
  51. package/src/filters/filter-range-number.ts +62 -0
  52. package/src/filters/filter-select.ts +47 -0
  53. package/src/filters/filter-styles.ts +88 -0
  54. package/src/filters/index.ts +10 -0
  55. package/src/filters/ox-filters-form-base.ts +261 -0
  56. package/src/filters/registry.ts +54 -0
  57. package/src/filters/types.ts +47 -0
  58. package/src/index.ts +1 -0
  59. package/stories/ox-filter-form-barcode.stories.ts +97 -0
  60. package/stories/ox-filter-form-base.stories.ts +97 -0
  61. package/themes/app-theme.css +142 -0
  62. /package/{src/themes → themes}/form-theme.css +0 -0
@@ -0,0 +1,62 @@
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 } = 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
+ />
35
+ ~
36
+ <input
37
+ name=${name}
38
+ type="number"
39
+ placeholder="maximum"
40
+ .value=${to}
41
+ to
42
+ @keyup=${(e: KeyboardEvent) => {
43
+ if (e.key !== 'Enter') {
44
+ return
45
+ }
46
+ ;(e.target as HTMLElement).dispatchEvent(
47
+ new CustomEvent('filter-change', {
48
+ bubbles: true,
49
+ composed: true,
50
+ detail: {
51
+ name,
52
+ operator,
53
+ value: Array.from(
54
+ (e.target as HTMLElement).parentElement!.querySelectorAll('input[from], input[to]')
55
+ ).map(input => (input as HTMLInputElement).value)
56
+ }
57
+ })
58
+ )
59
+ }}
60
+ />
61
+ `
62
+ }
@@ -0,0 +1,47 @@
1
+ import '@operato/input/ox-checkbox.js'
2
+
3
+ import { html } from 'lit-html'
4
+
5
+ import { FilterSelectRenderer } from './types.js'
6
+
7
+ export const FilterSelect: FilterSelectRenderer = (filter, value, owner) => {
8
+ /* value는 filters-form이나 grid-header에서 처리되므로 이 곳에서는 무시한다. */
9
+ var { name, type, operator, options = [] } = filter
10
+
11
+ if (typeof options === 'function') {
12
+ options = options.call(filter, owner)
13
+ }
14
+
15
+ options = options.map((option: any) => {
16
+ switch (typeof option) {
17
+ case 'string':
18
+ return {
19
+ display: option,
20
+ value: option
21
+ }
22
+ case 'object':
23
+ return {
24
+ display: option.display,
25
+ value: option.value
26
+ }
27
+ default:
28
+ return option
29
+ }
30
+ })
31
+
32
+ return operator === 'in'
33
+ ? html`
34
+ ${options
35
+ ?.filter((option: { display: string; value: any }) => !!option)
36
+ .map(
37
+ (option: { display: string; value: any }) =>
38
+ html` <ox-checkbox option value=${option.value}>${option.display}</ox-checkbox> `
39
+ )}
40
+ `
41
+ : html`
42
+ ${options?.map(
43
+ (option: { display: string; value: any }) =>
44
+ html` <div option value=${option.value}>${option.display}&nbsp;</div> `
45
+ )}
46
+ `
47
+ }
@@ -0,0 +1,88 @@
1
+ import { css } from 'lit'
2
+
3
+ export const FilterStyles = css`
4
+ :host {
5
+ --ox-input-placeholder-color: var(--primary-color);
6
+
7
+ --ox-input-padding: var(--padding-narrow) var(--padding-default);
8
+ --ox-input-border: 1px solid rgba(0, 0, 0, 0.2);
9
+ --ox-input-focus-border: 1px solid var(--primary-color);
10
+ --ox-input-border-radius: var(--border-radius);
11
+ --ox-input-font: normal 14px var(--theme-font);
12
+ --ox-input-color: var(--primary-text-color);
13
+
14
+ --ox-filters-form-gap: var(--margin-wide);
15
+ --ox-filters-form-label-font: var(--label-font);
16
+ --ox-filters-form-label-color: var(--label-color);
17
+ --ox-select-padding: 0 var(--padding-narrow);
18
+ }
19
+
20
+ label {
21
+ font: var(--ox-filters-form-label-font);
22
+ color: var(--ox-filters-form-label-color);
23
+ }
24
+ span {
25
+ margin-right: var(--margin-narrow);
26
+ text-transform: capitalize;
27
+ }
28
+
29
+ input::placeholder {
30
+ color: var(--ox-input-placeholder-color);
31
+ opacity: 0.6;
32
+ }
33
+
34
+ ox-select,
35
+ input {
36
+ padding: var(--input-padding);
37
+ border: none;
38
+ border-bottom: var(--ox-input-border);
39
+ font: var(--ox-input-font);
40
+ color: var(--ox-input-color);
41
+ }
42
+
43
+ ox-select:focus,
44
+ input:focus {
45
+ outline: none;
46
+ border-bottom: var(--ox-input-focus-border);
47
+ color: var(--primary-color);
48
+ }
49
+ ox-select {
50
+ padding: var(--ox-select-padding);
51
+ }
52
+
53
+ input[type='number'] {
54
+ padding-right: var(--padding-narrow);
55
+ max-width: 90px;
56
+ }
57
+
58
+ input[type*='date'],
59
+ input[type*='time'],
60
+ input[type='week'],
61
+ input[type='month'] {
62
+ padding: 8px var(--padding-narrow) 8px var(--padding-default);
63
+ max-width: 170px;
64
+ }
65
+
66
+ @media only screen and (max-width: 460px) {
67
+ :host {
68
+ --ox-filters-form-label-font: bold 13px var(--theme-font);
69
+ --ox-input-font: normal 16px var(--theme-font);
70
+ --ox-filters-form-gap: var(--margin-narrow);
71
+ }
72
+
73
+ ox-checkbox {
74
+ margin-top: var(--margin-narrow);
75
+ }
76
+
77
+ input[from],
78
+ input[to] {
79
+ max-width: 44%;
80
+ }
81
+
82
+ input[type*='datetime'][from],
83
+ input[type*='datetime'][to] {
84
+ padding-right: var(--padding-narrow);
85
+ min-width: 91%;
86
+ }
87
+ }
88
+ `
@@ -0,0 +1,10 @@
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'
@@ -0,0 +1,261 @@
1
+ import '@operato/input/ox-checkbox.js'
2
+ import '@operato/input/ox-select.js'
3
+ import '@operato/popup/ox-popup-list.js'
4
+ import '@operato/input/ox-input-search.js'
5
+
6
+ import json5 from 'json5'
7
+ import { css, html, LitElement, PropertyValues, TemplateResult } from 'lit'
8
+ import { customElement, property, queryAsync } from 'lit/decorators.js'
9
+
10
+ import { FilterStyles } from './filter-styles.js'
11
+ import { getFilterRenderer } from './registry.js'
12
+ import { FilterConfig, FilterOperator, FilterValue } from './types.js'
13
+
14
+ export type QueryFilterRangeValue = [from: number, to: number]
15
+
16
+ export type QueryFilter = {
17
+ name: string
18
+ operator: FilterOperator
19
+ value: any
20
+ }
21
+
22
+ @customElement('ox-filters-form-base')
23
+ export class FiltersFormBase extends LitElement {
24
+ static styles = [
25
+ FilterStyles,
26
+ css`
27
+ :host {
28
+ display: flex;
29
+ }
30
+
31
+ form {
32
+ flex: 1;
33
+
34
+ display: flex;
35
+ flex-flow: row wrap;
36
+ gap: var(--ox-filters-form-gap);
37
+ }
38
+
39
+ form > * {
40
+ display: flex;
41
+ align-items: center;
42
+ }
43
+
44
+ @media only screen and (max-width: 460px) {
45
+ form {
46
+ flex-direction: column;
47
+ }
48
+
49
+ label,
50
+ label span,
51
+ ox-select {
52
+ display: block;
53
+ }
54
+ }
55
+ `
56
+ ]
57
+
58
+ @property({ type: Object }) value: FilterValue[] = []
59
+ @property({ type: Object }) filters: FilterConfig[] = []
60
+ @property({ type: Boolean, attribute: 'url-params-sensitive' }) urlParamsSensitive?: boolean
61
+
62
+ @queryAsync('form') form!: HTMLFormElement
63
+
64
+ private _popstateEventHandler?: EventListener
65
+ private _filtersChangeHandler?: EventListener
66
+
67
+ connectedCallback(): void {
68
+ super.connectedCallback()
69
+
70
+ this.renderRoot.addEventListener('change', async (e: Event) => {
71
+ this.dispatchEvent(
72
+ new CustomEvent('filters-change', {
73
+ bubbles: true,
74
+ composed: true,
75
+ detail: {
76
+ filters: await this.getQueryFilters(),
77
+ from: 'filters-form'
78
+ }
79
+ })
80
+ )
81
+ })
82
+ }
83
+
84
+ render(): TemplateResult {
85
+ return html`
86
+ <form
87
+ @submit=${(e: Event) => {
88
+ e.preventDefault()
89
+ }}
90
+ >
91
+ ${this.filters.map((filter: FilterConfig) => {
92
+ const { name, label, type, operator } = filter
93
+ const idx = operator === 'between' ? 1 : 0
94
+ const renderer = getFilterRenderer(
95
+ operator === 'like' || operator === 'i_like' || operator === 'i_nlike' || operator === 'nlike'
96
+ ? 'text'
97
+ : type
98
+ )[idx]
99
+ const value = this.value?.find(filter => filter.name == name)?.value
100
+
101
+ if (!renderer) {
102
+ return html``
103
+ }
104
+
105
+ return type === 'search'
106
+ ? html`<ox-input-search name="search" .value=${value}></ox-input-search>`
107
+ : type !== 'select'
108
+ ? html` <label filter-title><span>${label}</span> ${renderer(filter, value, this)} </label> `
109
+ : operator === 'in'
110
+ ? html`
111
+ <ox-select
112
+ name=${name}
113
+ placeholder=${label}
114
+ .value=${value}
115
+ @change=${(e: CustomEvent) =>
116
+ e.target?.dispatchEvent(
117
+ new CustomEvent('filter-change', {
118
+ detail: {
119
+ name,
120
+ operator,
121
+ value: e.detail
122
+ }
123
+ })
124
+ )}
125
+ >
126
+ <ox-popup-list multiple attr-selected="checked" with-search>
127
+ ${renderer(filter, value, this)}
128
+ </ox-popup-list>
129
+ </ox-select>
130
+ `
131
+ : html`
132
+ <ox-select
133
+ name=${name}
134
+ placeholder=${label}
135
+ .value=${value}
136
+ @change=${(e: CustomEvent) =>
137
+ e.target?.dispatchEvent(
138
+ new CustomEvent('filter-change', {
139
+ detail: {
140
+ name,
141
+ operator,
142
+ value: e.detail
143
+ }
144
+ })
145
+ )}
146
+ >
147
+ <ox-popup-list with-search> ${renderer(filter, value, this)} </ox-popup-list>
148
+ </ox-select>
149
+ `
150
+ })}
151
+ </form>
152
+ `
153
+ }
154
+
155
+ async updated(changes: PropertyValues<this>) {
156
+ if (changes.has('urlParamsSensitive')) {
157
+ if (this.urlParamsSensitive) {
158
+ this._popstateEventHandler = () => {
159
+ const queryString = window.location.search
160
+ const urlParams = new URLSearchParams(queryString)
161
+ var filters = urlParams.get('filters')
162
+
163
+ if (filters) {
164
+ try {
165
+ this.value = json5.parse(filters)
166
+ this.dispatchEvent(
167
+ new CustomEvent('filters-change', {
168
+ bubbles: true,
169
+ composed: true,
170
+ detail: {
171
+ filters: json5.parse(filters),
172
+ from: 'url-parameter'
173
+ }
174
+ })
175
+ )
176
+ } catch (e) {
177
+ console.error(`invalid filters params on URL query string : ${e}`)
178
+ }
179
+ }
180
+ }
181
+
182
+ //@ts-ignore
183
+ this._popstateEventHandler() // call for the first time
184
+
185
+ window.addEventListener('popstate', this._popstateEventHandler)
186
+
187
+ this._filtersChangeHandler = (e: Event) => {
188
+ const urlParams = new URLSearchParams(window.location.search)
189
+ const { filters, from } = (e as CustomEvent).detail || {}
190
+
191
+ if (from === 'url-parameter') {
192
+ return
193
+ }
194
+
195
+ if (filters.length > 0) {
196
+ urlParams.set('filters', json5.stringify(filters))
197
+ } else {
198
+ urlParams.delete('filters')
199
+ }
200
+ const queryString = String(urlParams)
201
+ const url = `${window.location.pathname}${queryString ? `?${queryString}` : ''}`
202
+
203
+ history.pushState({}, document.title, url)
204
+ }
205
+
206
+ this.addEventListener('filters-change', this._filtersChangeHandler)
207
+ } else {
208
+ if (this._popstateEventHandler) {
209
+ window.removeEventListener('popstate', this._popstateEventHandler)
210
+ }
211
+ if (this._filtersChangeHandler) {
212
+ this.removeEventListener('popstate', this._filtersChangeHandler)
213
+ }
214
+ }
215
+ }
216
+ }
217
+
218
+ async getQueryFilters(): Promise<QueryFilter[]> {
219
+ const formData = new FormData(await this.form)
220
+
221
+ var filters = this.filters
222
+ .map((filter: FilterConfig) => {
223
+ const { name, type, operator } = filter
224
+
225
+ var value = formData.getAll(name)
226
+ if (value.length == 0) {
227
+ return
228
+ }
229
+
230
+ if (-1 === value.findIndex(v => v !== '')) {
231
+ return
232
+ }
233
+
234
+ const filterValue = value.map(v => {
235
+ const value = v.toString()
236
+
237
+ /* TODO registry에서 타입별로 parsing 방법을 지정할 수 있도록 해야한다. */
238
+ switch (type) {
239
+ case 'integer':
240
+ case 'float':
241
+ case 'number':
242
+ case 'progress':
243
+ case 'checkbox':
244
+ case 'boolean':
245
+ return !value ? undefined : JSON.parse(value)
246
+ default:
247
+ return value
248
+ }
249
+ })
250
+
251
+ return {
252
+ name,
253
+ operator,
254
+ value: filterValue.length === 1 ? filterValue[0] : filterValue
255
+ }
256
+ })
257
+ .filter(result => result !== undefined) as QueryFilter[]
258
+
259
+ return filters
260
+ }
261
+ }
@@ -0,0 +1,54 @@
1
+ import { FilterCheckbox } from './filter-checkbox.js'
2
+ import { FilterInputBarcode } from './filter-input-barcode.js'
3
+ import { FilterInput } from './filter-input.js'
4
+ import { FilterRangeDate } from './filter-range-date.js'
5
+ import { FilterRangeNumber } from './filter-range-number.js'
6
+ import { FilterSelect } from './filter-select.js'
7
+ import { FilterSelectRenderer } from './types.js'
8
+
9
+ var RENDERERS: {
10
+ [name: string]: FilterSelectRenderer[]
11
+ } = {
12
+ string: [FilterInput],
13
+ text: [FilterInput],
14
+ email: [FilterInput],
15
+ tel: [FilterInput],
16
+ integer: [FilterInput, FilterRangeNumber],
17
+ float: [FilterInput, FilterRangeNumber],
18
+ number: [FilterInput, FilterRangeNumber],
19
+ select: [FilterSelect],
20
+ boolean: [FilterCheckbox],
21
+ checkbox: [FilterCheckbox],
22
+ month: [FilterInput, FilterRangeDate],
23
+ week: [FilterInput, FilterRangeDate],
24
+ date: [FilterInput, FilterRangeDate],
25
+ time: [FilterInput, FilterRangeDate],
26
+ datetime: [FilterInput, FilterRangeDate],
27
+ color: [FilterInput],
28
+ progress: [FilterInput, FilterRangeNumber],
29
+ link: [FilterInput],
30
+ image: [FilterInput],
31
+ json5: [FilterInput],
32
+ scanner: [FilterInputBarcode],
33
+ barcode: [FilterInputBarcode]
34
+ }
35
+
36
+ export function registerFilterRenderer(type: string, renderer: FilterSelectRenderer[]) {
37
+ RENDERERS[type] = renderer
38
+ }
39
+
40
+ export function unregisterFilterRenderer(type: string): void {
41
+ delete RENDERERS[type]
42
+ }
43
+
44
+ export function getFilterRenderers(): { [name: string]: FilterSelectRenderer[] } {
45
+ return { ...RENDERERS }
46
+ }
47
+
48
+ export function getFilterRenderer(type: string): FilterSelectRenderer[] {
49
+ if (typeof type == 'function') {
50
+ return type
51
+ }
52
+
53
+ return RENDERERS[type || 'text'] || [FilterInput]
54
+ }
@@ -0,0 +1,47 @@
1
+ import { TemplateResult } from 'lit-html'
2
+
3
+ export type FilterOperator =
4
+ | 'search'
5
+ | 'eq'
6
+ | 'between'
7
+ | 'gte'
8
+ | 'lte'
9
+ | 'is_not_true'
10
+ | 'in'
11
+ | 'like'
12
+ | 'i_like'
13
+ | 'noteq'
14
+ | 'is_empty_num_id'
15
+ | 'is_blank'
16
+ | 'is_present'
17
+ | 'is_not_false'
18
+ | 'is_true'
19
+ | 'is_false'
20
+ | 'is_not_null'
21
+ | 'is_null'
22
+ | 'notin_with_null'
23
+ | 'notin'
24
+ | 'gt'
25
+ | 'lt'
26
+ | 'i_nlike'
27
+ | 'nlike'
28
+
29
+ export type FilterConfig = {
30
+ name: string
31
+ label: string
32
+ type: string
33
+ operator?: FilterOperator
34
+ options?: { [key: string]: any }
35
+ }
36
+
37
+ export type FilterValue = {
38
+ name: string
39
+ operator: FilterOperator
40
+ value: string | number | boolean | string[] | number[] | undefined
41
+ }
42
+
43
+ export type FilterSelectRenderer = (
44
+ filter: FilterConfig,
45
+ value: string | number | boolean | string[] | number[] | any | undefined,
46
+ owner: Element
47
+ ) => TemplateResult | string | void
package/src/index.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export * from './styles'
2
2
  export * from './components/ox-search-form'
3
3
  export * from './components/ox-file-uploader'
4
+ export * from './filters'
@@ -0,0 +1,97 @@
1
+ import '../src/filters/ox-filters-form-base.js'
2
+
3
+ import { html, TemplateResult } from 'lit'
4
+
5
+ export default {
6
+ title: 'ox-filters-form-barcode',
7
+ component: 'ox-filters-form-barcode',
8
+ argTypes: {
9
+ value: { control: 'object' },
10
+ filters: { control: 'object' },
11
+ urlParamsSensitive: { control: 'boolean' }
12
+ }
13
+ }
14
+
15
+ interface Story<T> {
16
+ (args: T): TemplateResult
17
+ args?: Partial<T>
18
+ argTypes?: Record<string, unknown>
19
+ }
20
+
21
+ interface ArgTypes {
22
+ value?: object
23
+ filters?: object
24
+ urlParamsSensitive: boolean
25
+ }
26
+
27
+ const Template: Story<ArgTypes> = ({ value, filters, urlParamsSensitive }: ArgTypes) => html`
28
+ <link href="/themes/app-theme.css" rel="stylesheet" />
29
+ <link href="/themes/form-theme.css" rel="stylesheet" />
30
+ <link href="https://fonts.googleapis.com/css?family=Material+Icons&display=block" rel="stylesheet" />
31
+ <style>
32
+ body {
33
+ }
34
+ </style>
35
+
36
+ <ox-filters-form-base
37
+ .value=${value}
38
+ .filters=${filters}
39
+ ?url-params-sensitive=${urlParamsSensitive}
40
+ @filters-change=${(e: CustomEvent) => {
41
+ console.log('filters changed', e.detail)
42
+ }}
43
+ >
44
+ </ox-filters-form-base>
45
+ `
46
+
47
+ export const Regular = Template.bind({})
48
+ Regular.args = {
49
+ filters: [
50
+ {
51
+ name: 'test',
52
+ type: 'barcode',
53
+ label: 'name',
54
+ operator: 'eq'
55
+ },
56
+ {
57
+ name: 'active',
58
+ type: 'boolean',
59
+ label: 'active',
60
+ operator: 'eq'
61
+ },
62
+ {
63
+ name: 'sss',
64
+ type: 'select',
65
+ label: 'sss',
66
+ operator: 'eq',
67
+ options: () => {
68
+ return [
69
+ {
70
+ display: '',
71
+ value: ''
72
+ },
73
+ {
74
+ display: 'ABC',
75
+ value: 'ABC'
76
+ },
77
+ {
78
+ display: 'DEF',
79
+ value: 'DEF'
80
+ }
81
+ ]
82
+ }
83
+ },
84
+ {
85
+ name: 'range',
86
+ type: 'number',
87
+ label: 'range',
88
+ operator: 'between'
89
+ },
90
+ {
91
+ name: 'date-range',
92
+ type: 'datetime',
93
+ label: 'date',
94
+ operator: 'between'
95
+ }
96
+ ]
97
+ }