@operato/data-grist 10.22.0 → 10.27.1

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 (32) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/dist/src/configure/rows-option-builder.js +2 -1
  3. package/dist/src/configure/rows-option-builder.js.map +1 -1
  4. package/dist/src/data-card/data-card-field.d.ts +1 -0
  5. package/dist/src/data-card/data-card-field.js +9 -1
  6. package/dist/src/data-card/data-card-field.js.map +1 -1
  7. package/dist/src/data-card/data-card-gutter.js +30 -12
  8. package/dist/src/data-card/data-card-gutter.js.map +1 -1
  9. package/dist/src/data-card/data-card.d.ts +7 -0
  10. package/dist/src/data-card/data-card.js +237 -2
  11. package/dist/src/data-card/data-card.js.map +1 -1
  12. package/dist/src/data-card/record-card.js +33 -2
  13. package/dist/src/data-card/record-card.js.map +1 -1
  14. package/dist/src/data-grid/data-grid-field.js +1 -1
  15. package/dist/src/data-grid/data-grid-field.js.map +1 -1
  16. package/dist/src/filters/filter-styles.js +1 -1
  17. package/dist/src/filters/filter-styles.js.map +1 -1
  18. package/dist/src/gutters/gutter-sequence.d.ts +1 -0
  19. package/dist/src/personalizer/ox-grist-filter-personalizer.d.ts +1 -1
  20. package/dist/src/personalizer/ox-grist-filter-personalizer.js +11 -45
  21. package/dist/src/personalizer/ox-grist-filter-personalizer.js.map +1 -1
  22. package/dist/src/personalizer/ox-grist-personalizer.d.ts +1 -1
  23. package/dist/src/personalizer/ox-grist-personalizer.js +23 -86
  24. package/dist/src/personalizer/ox-grist-personalizer.js.map +1 -1
  25. package/dist/src/personalizer/personalizer-chrome.d.ts +5 -0
  26. package/dist/src/personalizer/personalizer-chrome.js +165 -0
  27. package/dist/src/personalizer/personalizer-chrome.js.map +1 -0
  28. package/dist/src/types.d.ts +13 -0
  29. package/dist/src/types.js.map +1 -1
  30. package/dist/test/report-focused-row-theme.test.js.map +1 -0
  31. package/dist/tsconfig.tsbuildinfo +1 -1
  32. package/package.json +6 -6
@@ -1,9 +1,10 @@
1
1
  import { __decorate } from "tslib";
2
- import '@material/web/button/outlined-button.js';
2
+ import '@material/web/icon/icon.js';
3
3
  import { css, html, LitElement } from 'lit';
4
4
  import { customElement, property, state } from 'lit/decorators.js';
5
5
  import { i18next } from '@operato/i18n';
6
6
  import { OxPopupList } from '@operato/popup';
7
+ import { PERSONALIZER_POPUP_STYLES, personalizerFooter, personalizerHandle, personalizerHeader } from './personalizer-chrome.js';
7
8
  let OxGristFilterPersonalizer = class OxGristFilterPersonalizer extends LitElement {
8
9
  constructor() {
9
10
  super(...arguments);
@@ -36,40 +37,27 @@ let OxGristFilterPersonalizer = class OxGristFilterPersonalizer extends LitEleme
36
37
  };
37
38
  }) || []).filter(Boolean)
38
39
  };
39
- const template = html `
40
- <div class="personalizer-header" slot="header">
41
- <md-icon
42
- style="margin-left: auto;"
43
- @click=${async (e) => {
40
+ const save = async () => {
44
41
  if (form.personalConfigProvider) {
45
42
  form.personalConfig = await form.personalConfigProvider.save(this.preference);
46
43
  }
47
44
  popup.close();
48
- }}
49
- title=${String(i18next.t('button.save'))}
50
- >keep</md-icon
51
- ><md-icon
52
- @click=${async (e) => {
45
+ };
46
+ const reset = async () => {
53
47
  if (form.personalConfigProvider) {
54
48
  form.personalConfig = this.preference = {};
55
49
  await form.personalConfigProvider.reset();
56
50
  }
57
51
  popup.close();
58
- }}
59
- title=${String(i18next.t('button.delete'))}
60
- >keep_off</md-icon
61
- ><md-icon @click=${async (e) => popup.close()} title=${String(i18next.t('button.close'))}
62
- >close</md-icon
63
- >
64
- </div>
65
-
52
+ };
53
+ const template = html `
54
+ ${personalizerHeader(i18next.t('label.filters', { defaultValue: 'Filters' }), i18next.t('text.tick to show drag to reorder', { defaultValue: 'Tick to show, drag to reorder' }), () => popup.close())}
66
55
  ${(_a = this.preference) === null || _a === void 0 ? void 0 : _a.filters.map(filter => html `
67
56
  <ox-checkbox label="checkbox" ?checked=${!filter.hidden} value=${filter.name} option
68
- >${filter.name}<span style="position: absolute; right: 10px; cursor: row-resize;opacity:.5" handle
69
- >☰</span
70
- ></ox-checkbox
57
+ >${filter.name}${personalizerHandle()}</ox-checkbox
71
58
  >
72
59
  `)}
60
+ ${personalizerFooter(reset, save)}
73
61
  `;
74
62
  const popup = OxPopupList.open({
75
63
  template,
@@ -79,29 +67,7 @@ let OxGristFilterPersonalizer = class OxGristFilterPersonalizer extends LitEleme
79
67
  attrSelected: 'checked',
80
68
  top: e.pageY,
81
69
  left: e.pageX,
82
- styles: css `
83
- :host {
84
- width: 240px;
85
- min-height: 300px;
86
- max-height: 80%;
87
- overflow: auto;
88
- }
89
-
90
- ::slotted(.personalizer-header) {
91
- --md-icon-size: 1.4em;
92
-
93
- display: flex;
94
- flex-direction: row;
95
- align-items: center;
96
- text-transform: capitalize;
97
- box-shadow: 0 3px 3px rgba(0, 0, 0, 0.3);
98
- }
99
-
100
- ::slotted([option]) {
101
- position: relative;
102
- user-select: none;
103
- }
104
- `
70
+ styles: PERSONALIZER_POPUP_STYLES
105
71
  });
106
72
  popup.onselect = (e) => {
107
73
  var _a;
@@ -1 +1 @@
1
- {"version":3,"file":"ox-grist-filter-personalizer.js","sourceRoot":"","sources":["../../../src/personalizer/ox-grist-filter-personalizer.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/button/outlined-button.js'\n\nimport { css, html, LitElement } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\n\nimport { i18next } from '@operato/i18n'\nimport { OxPopupList } from '@operato/popup'\n\nimport { FilterConfigObject, FilterPreference, PersonalGristPreference } from '../types.js'\n\nimport { OxFiltersForm } from '../filters/filters-form.js'\n\n@customElement('ox-grist-filter-personalizer')\nexport class OxGristFilterPersonalizer extends LitElement {\n static styles = [\n css`\n md-icon {\n --md-icon-size: 16px;\n width: 36px;\n height: 36px;\n color: var(--md-sys-color-secondary-container);\n cursor: pointer;\n\n display: flex;\n place-content: center;\n place-items: center;\n position: relative;\n\n &:hover {\n color: var(--md-sys-color-primary-container);\n }\n }\n\n md-ripple {\n border-radius: 50%;\n inset: unset;\n height: 36px;\n width: 36px;\n }\n `\n ]\n\n @property({ type: Boolean, attribute: true }) debug: boolean = false\n\n @state() private preference?: PersonalGristPreference\n\n render() {\n return html`\n <md-icon\n @click=${async (e: MouseEvent) => {\n const form = this.closest('ox-filters-form') as OxFiltersForm\n const { filterColumns, personalFilters = [] } = form\n const queryFilters = await form.getQueryFilters()\n\n this.preference = {\n filters: (\n personalFilters.map((filter: FilterPreference) => {\n const originFilterColumn =\n filter.name == 'search'\n ? { filter: { name: 'search' } }\n : filterColumns.find(f => f.name == filter.name)\n\n if (!originFilterColumn) {\n /* 원래 filters 설정에 있는 것들 만을 유지한다. */\n return\n }\n\n const { value } = originFilterColumn.filter! as FilterConfigObject\n\n return {\n name: filter.name,\n hidden: filter.hidden,\n /* 만약, filters에 기본값이 이미 설정되어 있다면, 그대로 유지한다. */\n value: value ?? queryFilters.find(f => f.name == filter.name)?.value\n }\n }) || []\n ).filter(Boolean) as FilterPreference[]\n }\n\n const template = html`\n <div class=\"personalizer-header\" slot=\"header\">\n <md-icon\n style=\"margin-left: auto;\"\n @click=${async (e: MouseEvent) => {\n if (form.personalConfigProvider) {\n form.personalConfig = await form.personalConfigProvider.save(this.preference)\n }\n popup.close()\n }}\n title=${String(i18next.t('button.save'))}\n >keep</md-icon\n ><md-icon\n @click=${async (e: MouseEvent) => {\n if (form.personalConfigProvider) {\n form.personalConfig = this.preference = {}\n await form.personalConfigProvider.reset()\n }\n popup.close()\n }}\n title=${String(i18next.t('button.delete'))}\n >keep_off</md-icon\n ><md-icon @click=${async (e: MouseEvent) => popup.close()} title=${String(i18next.t('button.close'))}\n >close</md-icon\n >\n </div>\n\n ${this.preference?.filters!.map(\n filter => html`\n <ox-checkbox label=\"checkbox\" ?checked=${!filter.hidden} value=${filter.name} option\n >${filter.name}<span style=\"position: absolute; right: 10px; cursor: row-resize;opacity:.5\" handle\n >☰</span\n ></ox-checkbox\n >\n `\n )}\n `\n\n const popup = OxPopupList.open({\n template,\n multiple: true,\n sortable: true,\n debug: this.debug,\n attrSelected: 'checked',\n top: e.pageY,\n left: e.pageX,\n styles: css`\n :host {\n width: 240px;\n min-height: 300px;\n max-height: 80%;\n overflow: auto;\n }\n\n ::slotted(.personalizer-header) {\n --md-icon-size: 1.4em;\n\n display: flex;\n flex-direction: row;\n align-items: center;\n text-transform: capitalize;\n box-shadow: 0 3px 3px rgba(0, 0, 0, 0.3);\n }\n\n ::slotted([option]) {\n position: relative;\n user-select: none;\n }\n `\n })\n\n popup.onselect = (e: Event) => {\n const selected = (e as CustomEvent).detail\n\n const pconfig: PersonalGristPreference = { ...form.personalConfig }\n const pfilters = this.preference?.filters!\n\n pconfig.filters = pfilters.map(filter => {\n return {\n name: filter.name,\n hidden: selected.indexOf(filter.name) == -1,\n value: filter.value\n }\n })\n\n form.personalConfig = this.preference = pconfig\n\n form.applyUpdatedConfiguration()\n }\n\n popup.addEventListener('sorted', (e: Event) => {\n const sorted = (e as CustomEvent).detail as HTMLElement[]\n\n const pconfig: PersonalGristPreference = { ...form.personalConfig }\n const pfilters = this.preference?.filters!\n\n pconfig.filters = sorted\n .map(element => {\n const name = (element as HTMLInputElement).value\n return pfilters.find(filter => filter.name == name)!\n })\n .filter(Boolean)\n\n form.personalConfig = this.preference = pconfig\n\n form.applyUpdatedConfiguration()\n })\n }}\n >settings<md-ripple></md-ripple\n ></md-icon>\n `\n }\n}\n"]}
1
+ {"version":3,"file":"ox-grist-filter-personalizer.js","sourceRoot":"","sources":["../../../src/personalizer/ox-grist-filter-personalizer.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\n\nimport { css, html, LitElement } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\n\nimport { i18next } from '@operato/i18n'\nimport { OxPopupList } from '@operato/popup'\n\nimport { FilterConfigObject, FilterPreference, PersonalGristPreference } from '../types.js'\n\nimport { OxFiltersForm } from '../filters/filters-form.js'\nimport { PERSONALIZER_POPUP_STYLES, personalizerFooter, personalizerHandle, personalizerHeader } from './personalizer-chrome.js'\n\n@customElement('ox-grist-filter-personalizer')\nexport class OxGristFilterPersonalizer extends LitElement {\n static styles = [\n css`\n md-icon {\n --md-icon-size: 16px;\n width: 36px;\n height: 36px;\n color: var(--md-sys-color-secondary-container);\n cursor: pointer;\n\n display: flex;\n place-content: center;\n place-items: center;\n position: relative;\n\n &:hover {\n color: var(--md-sys-color-primary-container);\n }\n }\n\n md-ripple {\n border-radius: 50%;\n inset: unset;\n height: 36px;\n width: 36px;\n }\n `\n ]\n\n @property({ type: Boolean, attribute: true }) debug: boolean = false\n\n @state() private preference?: PersonalGristPreference\n\n render() {\n return html`\n <md-icon\n @click=${async (e: MouseEvent) => {\n const form = this.closest('ox-filters-form') as OxFiltersForm\n const { filterColumns, personalFilters = [] } = form\n const queryFilters = await form.getQueryFilters()\n\n this.preference = {\n filters: (\n personalFilters.map((filter: FilterPreference) => {\n const originFilterColumn =\n filter.name == 'search'\n ? { filter: { name: 'search' } }\n : filterColumns.find(f => f.name == filter.name)\n\n if (!originFilterColumn) {\n /* 원래 filters 설정에 있는 것들 만을 유지한다. */\n return\n }\n\n const { value } = originFilterColumn.filter! as FilterConfigObject\n\n return {\n name: filter.name,\n hidden: filter.hidden,\n /* 만약, filters에 기본값이 이미 설정되어 있다면, 그대로 유지한다. */\n value: value ?? queryFilters.find(f => f.name == filter.name)?.value\n }\n }) || []\n ).filter(Boolean) as FilterPreference[]\n }\n\n const save = async () => {\n if (form.personalConfigProvider) {\n form.personalConfig = await form.personalConfigProvider.save(this.preference)\n }\n popup.close()\n }\n\n const reset = async () => {\n if (form.personalConfigProvider) {\n form.personalConfig = this.preference = {}\n await form.personalConfigProvider.reset()\n }\n popup.close()\n }\n\n const template = html`\n ${personalizerHeader(\n i18next.t('label.filters', { defaultValue: 'Filters' }),\n i18next.t('text.tick to show drag to reorder', { defaultValue: 'Tick to show, drag to reorder' }),\n () => popup.close()\n )}\n ${this.preference?.filters!.map(\n filter => html`\n <ox-checkbox label=\"checkbox\" ?checked=${!filter.hidden} value=${filter.name} option\n >${filter.name}${personalizerHandle()}</ox-checkbox\n >\n `\n )}\n ${personalizerFooter(reset, save)}\n `\n\n const popup = OxPopupList.open({\n template,\n multiple: true,\n sortable: true,\n debug: this.debug,\n attrSelected: 'checked',\n top: e.pageY,\n left: e.pageX,\n styles: PERSONALIZER_POPUP_STYLES\n })\n\n popup.onselect = (e: Event) => {\n const selected = (e as CustomEvent).detail\n\n const pconfig: PersonalGristPreference = { ...form.personalConfig }\n const pfilters = this.preference?.filters!\n\n pconfig.filters = pfilters.map(filter => {\n return {\n name: filter.name,\n hidden: selected.indexOf(filter.name) == -1,\n value: filter.value\n }\n })\n\n form.personalConfig = this.preference = pconfig\n\n form.applyUpdatedConfiguration()\n }\n\n popup.addEventListener('sorted', (e: Event) => {\n const sorted = (e as CustomEvent).detail as HTMLElement[]\n\n const pconfig: PersonalGristPreference = { ...form.personalConfig }\n const pfilters = this.preference?.filters!\n\n pconfig.filters = sorted\n .map(element => {\n const name = (element as HTMLInputElement).value\n return pfilters.find(filter => filter.name == name)!\n })\n .filter(Boolean)\n\n form.personalConfig = this.preference = pconfig\n\n form.applyUpdatedConfiguration()\n })\n }}\n >settings<md-ripple></md-ripple\n ></md-icon>\n `\n }\n}\n"]}
@@ -1,4 +1,4 @@
1
- import '@material/web/button/outlined-button.js';
1
+ import '@material/web/icon/icon.js';
2
2
  import { LitElement } from 'lit';
3
3
  export declare class OxGristPersonalizer extends LitElement {
4
4
  static styles: import("lit").CSSResult[];
@@ -1,9 +1,10 @@
1
1
  import { __decorate } from "tslib";
2
- import '@material/web/button/outlined-button.js';
2
+ import '@material/web/icon/icon.js';
3
3
  import { css, html, LitElement } from 'lit';
4
4
  import { customElement, property, state } from 'lit/decorators.js';
5
5
  import { i18next } from '@operato/i18n';
6
6
  import { OxPopupList } from '@operato/popup';
7
+ import { PERSONALIZER_POPUP_STYLES, personalizerFooter, personalizerHandle, personalizerHeader } from './personalizer-chrome.js';
7
8
  let OxGristPersonalizer = class OxGristPersonalizer extends LitElement {
8
9
  constructor() {
9
10
  super(...arguments);
@@ -37,21 +38,7 @@ let OxGristPersonalizer = class OxGristPersonalizer extends LitElement {
37
38
  },
38
39
  mode
39
40
  };
40
- const template = html `
41
- <div class="personalizer-header" slot="header">
42
- <div
43
- style=${`
44
- display: flex;
45
- align-items: center;
46
- margin: 0 0 0 auto;
47
- min-height: 1.4em;
48
- color: var(--ox-grist-p13n-button-color, var(--md-sys-color-on-primary));
49
- background-color: var(--ox-grist-p13n-button-background-color, var(--md-sys-color-primary));
50
- border-radius: var(--md-sys-shape-corner-small);
51
- padding: 0 var(--spacing-small);
52
- cursor: pointer;
53
- `}
54
- @click=${async (e) => {
41
+ const save = async () => {
55
42
  if (grist.personalConfigProvider) {
56
43
  const { mode, columns, sorters, pagination } = this.preference || {};
57
44
  grist.personalConfig = this.preference = await grist.personalConfigProvider.save({
@@ -62,53 +49,22 @@ let OxGristPersonalizer = class OxGristPersonalizer extends LitElement {
62
49
  });
63
50
  }
64
51
  popup.close();
65
- }}
66
- >
67
- ${String(i18next.t('button.save'))}
68
- </div>
69
- <div
70
- style=${`
71
- display: flex;
72
- align-items: center;
73
- margin: 0 0 0 var(--spacing-small, 4px);
74
- min-height: 1.4em;
75
- color: var(--ox-grist-p13n-button-color, var(--md-sys-color-on-primary));
76
- background-color: var(--ox-grist-p13n-button-background-color, var(--md-sys-color-primary));
77
- border-radius: var(--md-sys-shape-corner-small);
78
- padding: 0 var(--spacing-small);
79
- cursor: pointer;
80
- `}
81
- @click=${async (e) => {
52
+ };
53
+ const reset = async () => {
82
54
  if (grist.personalConfigProvider) {
83
55
  grist.personalConfig = this.preference = {};
84
56
  await grist.personalConfigProvider.reset();
85
57
  }
86
58
  popup.close();
87
- }}
88
- >
89
- ${String(i18next.t('button.delete'))}
90
- </div>
91
- <md-icon
92
- style=${`
93
- --md-icon-size: 1.2em;
94
- margin-left: var(--spacing-tiny, 2px);
95
- cursor: pointer;
96
- `}
97
- @click=${async (e) => popup.close()}
98
- title=${String(i18next.t('button.close'))}
99
- >close</md-icon
100
- >
101
- </div>
102
-
59
+ };
60
+ const template = html `
61
+ ${personalizerHeader(i18next.t('label.columns', { defaultValue: 'Columns' }), i18next.t('text.tick to show drag to reorder', { defaultValue: 'Tick to show, drag to reorder' }), () => popup.close())}
103
62
  ${columns.map(column => html `
104
63
  <ox-checkbox label="checkbox" ?checked=${!column.hidden} value=${column.name} option
105
- >${column.header.renderer(column)}<span
106
- style="position: absolute; right: 10px; cursor: row-resize;opacity:.5"
107
- handle
108
- >☰</span
109
- ></ox-checkbox
64
+ >${column.header.renderer(column)}${personalizerHandle()}</ox-checkbox
110
65
  >
111
66
  `)}
67
+ ${personalizerFooter(reset, save)}
112
68
  `;
113
69
  const popup = OxPopupList.open({
114
70
  template,
@@ -118,29 +74,7 @@ let OxGristPersonalizer = class OxGristPersonalizer extends LitElement {
118
74
  attrSelected: 'checked',
119
75
  top: e.pageY,
120
76
  left: e.pageX,
121
- styles: css `
122
- :host {
123
- width: 240px;
124
- min-height: 300px;
125
- max-height: 80%;
126
- overflow: auto;
127
- }
128
-
129
- ::slotted(.personalizer-header) {
130
- --md-icon-size: 1.4em;
131
-
132
- display: flex;
133
- flex-direction: row;
134
- align-items: center;
135
- text-transform: capitalize;
136
- box-shadow: 0 3px 3px rgba(0, 0, 0, 0.3);
137
- }
138
-
139
- ::slotted([option]) {
140
- position: relative;
141
- user-select: none;
142
- }
143
- `
77
+ styles: PERSONALIZER_POPUP_STYLES
144
78
  });
145
79
  popup.onselect = (e) => {
146
80
  var _a;
@@ -182,19 +116,22 @@ let OxGristPersonalizer = class OxGristPersonalizer extends LitElement {
182
116
  };
183
117
  OxGristPersonalizer.styles = [
184
118
  css `
119
+ /* The door to the list: a quiet glyph at the end of the header row. */
185
120
  md-icon {
186
- --md-icon-size: 14px;
187
- width: 16px;
188
- height: 16px;
189
- color: var(--ox-grist-p13n-color, var(--md-sys-color-on-primary));
190
- background-color: var(--ox-grist-p13n-background-color, var(--md-sys-color-primary));
191
- border-radius: 0px 0px 7px 7px;
121
+ --md-icon-size: 16px;
122
+ width: 22px;
123
+ height: 22px;
124
+ display: inline-flex;
125
+ align-items: center;
126
+ justify-content: center;
127
+ border-radius: 6px;
128
+ color: var(--ox-grist-p13n-color, var(--md-sys-color-on-surface-variant));
129
+ background-color: var(--ox-grist-p13n-background-color, transparent);
192
130
  cursor: pointer;
193
- padding-top: var(--spacing-small);
194
131
 
195
132
  &:hover {
196
- color: var(--ox-grist-p13n-hover-color, var(--md-sys-color-on-primary));
197
- background-color: var(--ox-grist-p13n-hover-background-color, var(--md-sys-color-surface-tint));
133
+ color: var(--ox-grist-p13n-hover-color, var(--md-sys-color-on-surface));
134
+ background-color: var(--ox-grist-p13n-hover-background-color, var(--md-sys-color-surface-container-high));
198
135
  }
199
136
  }
200
137
  `
@@ -1 +1 @@
1
- {"version":3,"file":"ox-grist-personalizer.js","sourceRoot":"","sources":["../../../src/personalizer/ox-grist-personalizer.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/button/outlined-button.js'\n\nimport { css, html, LitElement } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\n\nimport { i18next } from '@operato/i18n'\nimport { OxPopupList } from '@operato/popup'\nimport { OxCheckbox } from '@operato/input'\n\nimport { ColumnConfig, PersonalGristPreference } from '../types.js'\nimport { DataGrist } from '../data-grist.js'\n\n@customElement('ox-grist-personalizer')\nexport class OxGristPersonalizer extends LitElement {\n static styles = [\n css`\n md-icon {\n --md-icon-size: 14px;\n width: 16px;\n height: 16px;\n color: var(--ox-grist-p13n-color, var(--md-sys-color-on-primary));\n background-color: var(--ox-grist-p13n-background-color, var(--md-sys-color-primary));\n border-radius: 0px 0px 7px 7px;\n cursor: pointer;\n padding-top: var(--spacing-small);\n\n &:hover {\n color: var(--ox-grist-p13n-hover-color, var(--md-sys-color-on-primary));\n background-color: var(--ox-grist-p13n-hover-background-color, var(--md-sys-color-surface-tint));\n }\n }\n `\n ]\n\n @property({ type: Boolean, attribute: true }) debug: boolean = false\n\n @state() private preference?: PersonalGristPreference\n\n render() {\n return html`\n <md-icon\n @click=${(e: MouseEvent) => {\n const grist = this.closest('ox-grist') as DataGrist\n\n const { config, compiledConfig, sorters, pagination, mode } = grist\n const { columns: compiledColumns } = compiledConfig\n\n const columns = compiledColumns\n .filter(ccolumn => {\n const column = config.columns.find((column: Partial<ColumnConfig>) => column.name == ccolumn.name)\n return column && column.name && column.type !== 'gutter' && !column.hidden && !column.unusable\n })\n .map(column => compiledColumns.find(compiledColumn => compiledColumn.name == column.name)!)\n\n this.preference = {\n columns: columns.map(column => {\n return {\n name: column.name,\n hidden: column.hidden,\n width: column.width\n }\n }),\n sorters,\n pagination: {\n ...pagination,\n limit: grist.getCurrentLimit()\n },\n mode\n }\n\n const template = html`\n <div class=\"personalizer-header\" slot=\"header\">\n <div\n style=${`\n display: flex;\n align-items: center;\n margin: 0 0 0 auto;\n min-height: 1.4em;\n color: var(--ox-grist-p13n-button-color, var(--md-sys-color-on-primary));\n background-color: var(--ox-grist-p13n-button-background-color, var(--md-sys-color-primary));\n border-radius: var(--md-sys-shape-corner-small);\n padding: 0 var(--spacing-small);\n cursor: pointer;\n `}\n @click=${async (e: MouseEvent) => {\n if (grist.personalConfigProvider) {\n const { mode, columns, sorters, pagination } = this.preference || {}\n grist.personalConfig = this.preference = await grist.personalConfigProvider.save({\n mode,\n columns,\n sorters,\n pagination\n })\n }\n popup.close()\n }}\n >\n ${String(i18next.t('button.save'))}\n </div>\n <div\n style=${`\n display: flex;\n align-items: center;\n margin: 0 0 0 var(--spacing-small, 4px);\n min-height: 1.4em;\n color: var(--ox-grist-p13n-button-color, var(--md-sys-color-on-primary));\n background-color: var(--ox-grist-p13n-button-background-color, var(--md-sys-color-primary));\n border-radius: var(--md-sys-shape-corner-small);\n padding: 0 var(--spacing-small);\n cursor: pointer;\n `}\n @click=${async (e: MouseEvent) => {\n if (grist.personalConfigProvider) {\n grist.personalConfig = this.preference = {}\n await grist.personalConfigProvider.reset()\n }\n popup.close()\n }}\n >\n ${String(i18next.t('button.delete'))}\n </div>\n <md-icon\n style=${`\n --md-icon-size: 1.2em;\n margin-left: var(--spacing-tiny, 2px);\n cursor: pointer;\n `}\n @click=${async (e: MouseEvent) => popup.close()}\n title=${String(i18next.t('button.close'))}\n >close</md-icon\n >\n </div>\n\n ${columns.map(\n column => html`\n <ox-checkbox label=\"checkbox\" ?checked=${!column.hidden} value=${column.name} option\n >${column.header.renderer(column)}<span\n style=\"position: absolute; right: 10px; cursor: row-resize;opacity:.5\"\n handle\n >☰</span\n ></ox-checkbox\n >\n `\n )}\n `\n\n const popup = OxPopupList.open({\n template,\n multiple: true,\n sortable: true,\n debug: this.debug,\n attrSelected: 'checked',\n top: e.pageY,\n left: e.pageX,\n styles: css`\n :host {\n width: 240px;\n min-height: 300px;\n max-height: 80%;\n overflow: auto;\n }\n\n ::slotted(.personalizer-header) {\n --md-icon-size: 1.4em;\n\n display: flex;\n flex-direction: row;\n align-items: center;\n text-transform: capitalize;\n box-shadow: 0 3px 3px rgba(0, 0, 0, 0.3);\n }\n\n ::slotted([option]) {\n position: relative;\n user-select: none;\n }\n `\n })\n\n popup.onselect = (e: Event) => {\n const selected = (e as CustomEvent).detail\n\n const pconfig: PersonalGristPreference = grist.personalConfig || {}\n const pcolumns = this.preference?.columns || columns\n\n pconfig.columns = pcolumns.map(column => {\n return {\n name: column.name,\n hidden: selected.indexOf(column.name) == -1,\n width: column.width\n }\n })\n\n this.preference = pconfig\n\n grist.personalConfig = this.preference\n\n grist.applyUpdatedConfiguration()\n }\n\n popup.addEventListener('sorted', (e: Event) => {\n const sorted = (e as CustomEvent).detail as HTMLElement[]\n\n const pconfig: PersonalGristPreference = grist.personalConfig || {}\n\n pconfig.columns = sorted.map(element => {\n const name = (element as OxCheckbox).value\n return {\n name,\n hidden: !element.hasAttribute('checked'),\n width: columns.find(column => column.name == name)?.width\n }\n })\n\n this.preference = pconfig\n\n grist.personalConfig = this.preference\n\n grist.applyUpdatedConfiguration()\n })\n }}\n >settings</md-icon\n >\n `\n }\n}\n"]}
1
+ {"version":3,"file":"ox-grist-personalizer.js","sourceRoot":"","sources":["../../../src/personalizer/ox-grist-personalizer.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\n\nimport { css, html, LitElement } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\n\nimport { i18next } from '@operato/i18n'\nimport { OxPopupList } from '@operato/popup'\nimport { OxCheckbox } from '@operato/input'\n\nimport { ColumnConfig, PersonalGristPreference } from '../types.js'\nimport { DataGrist } from '../data-grist.js'\nimport { PERSONALIZER_POPUP_STYLES, personalizerFooter, personalizerHandle, personalizerHeader } from './personalizer-chrome.js'\n\n@customElement('ox-grist-personalizer')\nexport class OxGristPersonalizer extends LitElement {\n static styles = [\n css`\n /* The door to the list: a quiet glyph at the end of the header row. */\n md-icon {\n --md-icon-size: 16px;\n width: 22px;\n height: 22px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border-radius: 6px;\n color: var(--ox-grist-p13n-color, var(--md-sys-color-on-surface-variant));\n background-color: var(--ox-grist-p13n-background-color, transparent);\n cursor: pointer;\n\n &:hover {\n color: var(--ox-grist-p13n-hover-color, var(--md-sys-color-on-surface));\n background-color: var(--ox-grist-p13n-hover-background-color, var(--md-sys-color-surface-container-high));\n }\n }\n `\n ]\n\n @property({ type: Boolean, attribute: true }) debug: boolean = false\n\n @state() private preference?: PersonalGristPreference\n\n render() {\n return html`\n <md-icon\n @click=${(e: MouseEvent) => {\n const grist = this.closest('ox-grist') as DataGrist\n\n const { config, compiledConfig, sorters, pagination, mode } = grist\n const { columns: compiledColumns } = compiledConfig\n\n const columns = compiledColumns\n .filter(ccolumn => {\n const column = config.columns.find((column: Partial<ColumnConfig>) => column.name == ccolumn.name)\n return column && column.name && column.type !== 'gutter' && !column.hidden && !column.unusable\n })\n .map(column => compiledColumns.find(compiledColumn => compiledColumn.name == column.name)!)\n\n this.preference = {\n columns: columns.map(column => {\n return {\n name: column.name,\n hidden: column.hidden,\n width: column.width\n }\n }),\n sorters,\n pagination: {\n ...pagination,\n limit: grist.getCurrentLimit()\n },\n mode\n }\n\n const save = async () => {\n if (grist.personalConfigProvider) {\n const { mode, columns, sorters, pagination } = this.preference || {}\n grist.personalConfig = this.preference = await grist.personalConfigProvider.save({\n mode,\n columns,\n sorters,\n pagination\n })\n }\n popup.close()\n }\n\n const reset = async () => {\n if (grist.personalConfigProvider) {\n grist.personalConfig = this.preference = {}\n await grist.personalConfigProvider.reset()\n }\n popup.close()\n }\n\n const template = html`\n ${personalizerHeader(\n i18next.t('label.columns', { defaultValue: 'Columns' }),\n i18next.t('text.tick to show drag to reorder', { defaultValue: 'Tick to show, drag to reorder' }),\n () => popup.close()\n )}\n ${columns.map(\n column => html`\n <ox-checkbox label=\"checkbox\" ?checked=${!column.hidden} value=${column.name} option\n >${column.header.renderer(column)}${personalizerHandle()}</ox-checkbox\n >\n `\n )}\n ${personalizerFooter(reset, save)}\n `\n\n const popup = OxPopupList.open({\n template,\n multiple: true,\n sortable: true,\n debug: this.debug,\n attrSelected: 'checked',\n top: e.pageY,\n left: e.pageX,\n styles: PERSONALIZER_POPUP_STYLES\n })\n\n popup.onselect = (e: Event) => {\n const selected = (e as CustomEvent).detail\n\n const pconfig: PersonalGristPreference = grist.personalConfig || {}\n const pcolumns = this.preference?.columns || columns\n\n pconfig.columns = pcolumns.map(column => {\n return {\n name: column.name,\n hidden: selected.indexOf(column.name) == -1,\n width: column.width\n }\n })\n\n this.preference = pconfig\n\n grist.personalConfig = this.preference\n\n grist.applyUpdatedConfiguration()\n }\n\n popup.addEventListener('sorted', (e: Event) => {\n const sorted = (e as CustomEvent).detail as HTMLElement[]\n\n const pconfig: PersonalGristPreference = grist.personalConfig || {}\n\n pconfig.columns = sorted.map(element => {\n const name = (element as OxCheckbox).value\n return {\n name,\n hidden: !element.hasAttribute('checked'),\n width: columns.find(column => column.name == name)?.width\n }\n })\n\n this.preference = pconfig\n\n grist.personalConfig = this.preference\n\n grist.applyUpdatedConfiguration()\n })\n }}\n >settings</md-icon\n >\n `\n }\n}\n"]}
@@ -0,0 +1,5 @@
1
+ import { TemplateResult } from 'lit';
2
+ export declare const PERSONALIZER_POPUP_STYLES: import("lit").CSSResult;
3
+ export declare function personalizerHeader(title: string, hint: string, onClose: () => void): TemplateResult;
4
+ export declare function personalizerHandle(): TemplateResult;
5
+ export declare function personalizerFooter(onReset: () => void, onSave: () => void): TemplateResult;
@@ -0,0 +1,165 @@
1
+ import { css, html } from 'lit';
2
+ import { i18next } from '@operato/i18n';
3
+ /*
4
+ * The shell both personalizers share: what the list is for at the top, the rows in the middle,
5
+ * and the two things a person can do with the result at the foot.
6
+ *
7
+ * The rows are light-DOM children of the popup, so the popup's own stylesheet reaches only their
8
+ * outer box (::slotted). The parts inside a row and the chrome around it are styled by the small
9
+ * sheet below, carried inside the template under one class so it touches nothing else.
10
+ */
11
+ export const PERSONALIZER_POPUP_STYLES = css `
12
+ :host {
13
+ width: 280px;
14
+ min-height: 0;
15
+ max-height: min(80vh, 560px);
16
+ padding: 0;
17
+ overflow: auto;
18
+ border-radius: 12px;
19
+ box-shadow: 0 8px 28px rgba(0, 0, 0, 0.18);
20
+ }
21
+
22
+ ::slotted([option]) {
23
+ display: flex;
24
+ align-items: center;
25
+ position: relative;
26
+ padding: 5px 36px 5px 14px;
27
+ border: 0;
28
+ border-left: 0;
29
+ font-size: 0.8rem;
30
+ /* A list of a dozen ticks wants a small mark; the row, not the box, is the target. */
31
+ --ox-checkbox-size: 12px;
32
+ --ox-checkbox-border-radius: 3px;
33
+ --input-intra-gap: 9px;
34
+ color: var(--md-sys-color-on-surface);
35
+ user-select: none;
36
+ }
37
+
38
+ ::slotted([option]:hover) {
39
+ background-color: var(--md-sys-color-surface-container-high);
40
+ color: var(--md-sys-color-on-surface);
41
+ }
42
+
43
+ ::slotted(.ox-p13n-header),
44
+ ::slotted(.ox-p13n-footer) {
45
+ padding: 0;
46
+ border: 0;
47
+ cursor: default;
48
+ }
49
+ `;
50
+ const SHEET = html `
51
+ <style>
52
+ .ox-p13n-header {
53
+ display: flex;
54
+ align-items: flex-start;
55
+ gap: 8px;
56
+ padding: 14px 10px 8px 16px;
57
+ background: inherit;
58
+ }
59
+ .ox-p13n-header .ox-p13n-title {
60
+ flex: 1;
61
+ min-width: 0;
62
+ line-height: 1.3;
63
+ }
64
+ .ox-p13n-header b {
65
+ display: block;
66
+ font-size: 0.86rem;
67
+ font-weight: 600;
68
+ color: var(--md-sys-color-on-surface);
69
+ }
70
+ /* Translations arrive in whatever case the catalogue keeps; a title starts with a capital. */
71
+ .ox-p13n-header b::first-letter,
72
+ .ox-p13n-header small::first-letter {
73
+ text-transform: uppercase;
74
+ }
75
+ .ox-p13n-header small {
76
+ display: block;
77
+ font-size: 0.72rem;
78
+ color: var(--md-sys-color-on-surface-variant);
79
+ }
80
+ .ox-p13n-header md-icon {
81
+ --md-icon-size: 18px;
82
+ flex: none;
83
+ padding: 4px;
84
+ border-radius: 8px;
85
+ color: var(--md-sys-color-outline);
86
+ cursor: pointer;
87
+ }
88
+ .ox-p13n-header md-icon:hover {
89
+ color: var(--md-sys-color-on-surface);
90
+ background: var(--md-sys-color-surface-container-high);
91
+ }
92
+ /* The row is a checkbox whose slot is inline, so the handle is pinned to the row's right edge. */
93
+ .ox-p13n-handle {
94
+ --md-icon-size: 18px;
95
+ position: absolute;
96
+ right: 10px;
97
+ top: 50%;
98
+ transform: translateY(-50%);
99
+ color: var(--md-sys-color-outline-variant);
100
+ cursor: grab;
101
+ }
102
+ [option]:hover .ox-p13n-handle {
103
+ color: var(--md-sys-color-outline);
104
+ }
105
+ .ox-p13n-footer {
106
+ position: sticky;
107
+ bottom: 0;
108
+ display: flex;
109
+ align-items: center;
110
+ justify-content: flex-end;
111
+ gap: 6px;
112
+ padding: 10px 12px 12px;
113
+ border-top: 1px solid var(--md-sys-color-outline-variant);
114
+ background: var(--ox-popup-list-background-color, var(--md-sys-color-surface-container-lowest));
115
+ }
116
+ .ox-p13n-footer button {
117
+ height: 28px;
118
+ padding: 0 12px;
119
+ border: 0;
120
+ border-radius: 999px;
121
+ background: transparent;
122
+ color: var(--md-sys-color-on-surface-variant);
123
+ font: inherit;
124
+ font-size: 0.78rem;
125
+ font-weight: 500;
126
+ cursor: pointer;
127
+ }
128
+ .ox-p13n-footer button:hover {
129
+ color: var(--md-sys-color-on-surface);
130
+ background: var(--md-sys-color-surface-container-high);
131
+ }
132
+ .ox-p13n-footer button[primary] {
133
+ padding: 0 16px;
134
+ color: var(--md-sys-color-on-primary);
135
+ background: var(--md-sys-color-primary);
136
+ }
137
+ .ox-p13n-footer button[primary]:hover {
138
+ color: var(--md-sys-color-on-primary);
139
+ background: var(--md-sys-color-primary);
140
+ filter: brightness(1.08);
141
+ }
142
+ </style>
143
+ `;
144
+ export function personalizerHeader(title, hint, onClose) {
145
+ return html `
146
+ ${SHEET}
147
+ <div class="ox-p13n-header" slot="header">
148
+ <div class="ox-p13n-title"><b>${title}</b><small>${hint}</small></div>
149
+ <md-icon @click=${onClose} title=${i18next.t('button.close', { defaultValue: 'Close' })}>close</md-icon>
150
+ </div>
151
+ `;
152
+ }
153
+ export function personalizerHandle() {
154
+ return html `<md-icon class="ox-p13n-handle" handle>drag_indicator</md-icon>`;
155
+ }
156
+ /* The list edits the screen as you go; the foot decides whether that outlives this visit. */
157
+ export function personalizerFooter(onReset, onSave) {
158
+ return html `
159
+ <div class="ox-p13n-footer">
160
+ <button @click=${onReset}>${i18next.t('button.reset to default', { defaultValue: 'Reset to default' })}</button>
161
+ <button primary @click=${onSave}>${i18next.t('button.save as mine', { defaultValue: 'Save as mine' })}</button>
162
+ </div>
163
+ `;
164
+ }
165
+ //# sourceMappingURL=personalizer-chrome.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"personalizer-chrome.js","sourceRoot":"","sources":["../../../src/personalizer/personalizer-chrome.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAkB,MAAM,KAAK,CAAA;AAE/C,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAEvC;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsC3C,CAAA;AAED,MAAM,KAAK,GAAG,IAAI,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6FjB,CAAA;AAED,MAAM,UAAU,kBAAkB,CAAC,KAAa,EAAE,IAAY,EAAE,OAAmB;IACjF,OAAO,IAAI,CAAA;MACP,KAAK;;sCAE2B,KAAK,cAAc,IAAI;wBACrC,OAAO,UAAU,OAAO,CAAC,CAAC,CAAC,cAAc,EAAE,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC;;GAE1F,CAAA;AACH,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,OAAO,IAAI,CAAA,iEAAiE,CAAA;AAC9E,CAAC;AAED,6FAA6F;AAC7F,MAAM,UAAU,kBAAkB,CAAC,OAAmB,EAAE,MAAkB;IACxE,OAAO,IAAI,CAAA;;uBAEU,OAAO,IAAI,OAAO,CAAC,CAAC,CAAC,yBAAyB,EAAE,EAAE,YAAY,EAAE,kBAAkB,EAAE,CAAC;+BAC7E,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,qBAAqB,EAAE,EAAE,YAAY,EAAE,cAAc,EAAE,CAAC;;GAExG,CAAA;AACH,CAAC","sourcesContent":["import { css, html, TemplateResult } from 'lit'\n\nimport { i18next } from '@operato/i18n'\n\n/*\n * The shell both personalizers share: what the list is for at the top, the rows in the middle,\n * and the two things a person can do with the result at the foot.\n *\n * The rows are light-DOM children of the popup, so the popup's own stylesheet reaches only their\n * outer box (::slotted). The parts inside a row and the chrome around it are styled by the small\n * sheet below, carried inside the template under one class so it touches nothing else.\n */\nexport const PERSONALIZER_POPUP_STYLES = css`\n :host {\n width: 280px;\n min-height: 0;\n max-height: min(80vh, 560px);\n padding: 0;\n overflow: auto;\n border-radius: 12px;\n box-shadow: 0 8px 28px rgba(0, 0, 0, 0.18);\n }\n\n ::slotted([option]) {\n display: flex;\n align-items: center;\n position: relative;\n padding: 5px 36px 5px 14px;\n border: 0;\n border-left: 0;\n font-size: 0.8rem;\n /* A list of a dozen ticks wants a small mark; the row, not the box, is the target. */\n --ox-checkbox-size: 12px;\n --ox-checkbox-border-radius: 3px;\n --input-intra-gap: 9px;\n color: var(--md-sys-color-on-surface);\n user-select: none;\n }\n\n ::slotted([option]:hover) {\n background-color: var(--md-sys-color-surface-container-high);\n color: var(--md-sys-color-on-surface);\n }\n\n ::slotted(.ox-p13n-header),\n ::slotted(.ox-p13n-footer) {\n padding: 0;\n border: 0;\n cursor: default;\n }\n`\n\nconst SHEET = html`\n <style>\n .ox-p13n-header {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n padding: 14px 10px 8px 16px;\n background: inherit;\n }\n .ox-p13n-header .ox-p13n-title {\n flex: 1;\n min-width: 0;\n line-height: 1.3;\n }\n .ox-p13n-header b {\n display: block;\n font-size: 0.86rem;\n font-weight: 600;\n color: var(--md-sys-color-on-surface);\n }\n /* Translations arrive in whatever case the catalogue keeps; a title starts with a capital. */\n .ox-p13n-header b::first-letter,\n .ox-p13n-header small::first-letter {\n text-transform: uppercase;\n }\n .ox-p13n-header small {\n display: block;\n font-size: 0.72rem;\n color: var(--md-sys-color-on-surface-variant);\n }\n .ox-p13n-header md-icon {\n --md-icon-size: 18px;\n flex: none;\n padding: 4px;\n border-radius: 8px;\n color: var(--md-sys-color-outline);\n cursor: pointer;\n }\n .ox-p13n-header md-icon:hover {\n color: var(--md-sys-color-on-surface);\n background: var(--md-sys-color-surface-container-high);\n }\n /* The row is a checkbox whose slot is inline, so the handle is pinned to the row's right edge. */\n .ox-p13n-handle {\n --md-icon-size: 18px;\n position: absolute;\n right: 10px;\n top: 50%;\n transform: translateY(-50%);\n color: var(--md-sys-color-outline-variant);\n cursor: grab;\n }\n [option]:hover .ox-p13n-handle {\n color: var(--md-sys-color-outline);\n }\n .ox-p13n-footer {\n position: sticky;\n bottom: 0;\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: 6px;\n padding: 10px 12px 12px;\n border-top: 1px solid var(--md-sys-color-outline-variant);\n background: var(--ox-popup-list-background-color, var(--md-sys-color-surface-container-lowest));\n }\n .ox-p13n-footer button {\n height: 28px;\n padding: 0 12px;\n border: 0;\n border-radius: 999px;\n background: transparent;\n color: var(--md-sys-color-on-surface-variant);\n font: inherit;\n font-size: 0.78rem;\n font-weight: 500;\n cursor: pointer;\n }\n .ox-p13n-footer button:hover {\n color: var(--md-sys-color-on-surface);\n background: var(--md-sys-color-surface-container-high);\n }\n .ox-p13n-footer button[primary] {\n padding: 0 16px;\n color: var(--md-sys-color-on-primary);\n background: var(--md-sys-color-primary);\n }\n .ox-p13n-footer button[primary]:hover {\n color: var(--md-sys-color-on-primary);\n background: var(--md-sys-color-primary);\n filter: brightness(1.08);\n }\n </style>\n`\n\nexport function personalizerHeader(title: string, hint: string, onClose: () => void): TemplateResult {\n return html`\n ${SHEET}\n <div class=\"ox-p13n-header\" slot=\"header\">\n <div class=\"ox-p13n-title\"><b>${title}</b><small>${hint}</small></div>\n <md-icon @click=${onClose} title=${i18next.t('button.close', { defaultValue: 'Close' })}>close</md-icon>\n </div>\n `\n}\n\nexport function personalizerHandle(): TemplateResult {\n return html`<md-icon class=\"ox-p13n-handle\" handle>drag_indicator</md-icon>`\n}\n\n/* The list edits the screen as you go; the foot decides whether that outlives this visit. */\nexport function personalizerFooter(onReset: () => void, onSave: () => void): TemplateResult {\n return html`\n <div class=\"ox-p13n-footer\">\n <button @click=${onReset}>${i18next.t('button.reset to default', { defaultValue: 'Reset to default' })}</button>\n <button primary @click=${onSave}>${i18next.t('button.save as mine', { defaultValue: 'Save as mine' })}</button>\n </div>\n `\n}\n"]}
@@ -308,6 +308,12 @@ export type ColumnConfig = {
308
308
  icon?: string;
309
309
  iconOnly?: boolean;
310
310
  danger?: boolean;
311
+ /**
312
+ * CARD mode, gutter columns: draw this button only while the card is hovered (or focused). A
313
+ * function decides per record - e.g. a favorite star that is quiet until set, then stays. On a
314
+ * device with no hover (touch) quiet gutters are always drawn, so nothing becomes unreachable.
315
+ */
316
+ quiet?: boolean | ((record: GristRecord) => boolean);
311
317
  /** [end] only for button gutter column */
312
318
  header: HeaderConfig;
313
319
  record: RecordConfig;
@@ -582,6 +588,12 @@ export type ImexConfig = {
582
588
  * @property {boolean} appendable - Indicates whether new rows can be appended to the table.
583
589
  * @property {boolean} insertable - Indicates whether new rows can be inserted into the table.
584
590
  * @property {RowSelectableConfig} [selectable] - Configuration for row selection options.
591
+ * @property {boolean} [reorderable] - CARD mode only: lets a viewer drag cards to reorder them.
592
+ * Dispatches a bubbling `reorder` CustomEvent on `ox-grist` (`detail: { ids: string[], movedId: string }`,
593
+ * the full record order after the move) instead of persisting anything itself - the consumer holds
594
+ * the actual ordering field and mutation, which differ per domain (an adjacency scheme, a stored
595
+ * array, ...). Off by default; a list still sorted server-side by some other field should leave this
596
+ * unset rather than let a drag silently not stick past the next fetch.
585
597
  * @property {GroupConfig[]} groups - An array of group configuration options.
586
598
  * @property {string[]} totals - An array of field names for which totals should be calculated and displayed.
587
599
  * @property {GristClassifier} classifier - A function that classifies rows based on their attributes.
@@ -593,6 +605,7 @@ export type RowsConfig = {
593
605
  editable: boolean;
594
606
  insertable: boolean;
595
607
  selectable?: RowSelectableConfig;
608
+ reorderable?: boolean;
596
609
  groups: GroupConfig[];
597
610
  totals: string[];
598
611
  classifier: GristClassifier;