@controleonline/ui-default 1.0.270 → 1.0.273

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 (100) hide show
  1. package/.github/workflows/integration-source-gate.yml +68 -0
  2. package/.github/workflows/manager-worker.yml +19 -0
  3. package/.github/workflows/publish-npm.yml +91 -0
  4. package/AGENTS.md +46 -50
  5. package/docs/technical/Contrato-de-colunas.md +67 -0
  6. package/docs/technical/Default-Components.md +76 -0
  7. package/docs/technical/DefaultForm.md +80 -0
  8. package/docs/technical/DefaultInput-e-DefaultSelect.md +73 -0
  9. package/docs/technical/DefaultTable.md +272 -0
  10. package/docs/wiki.md +1 -0
  11. package/package.json +4 -3
  12. package/scripts/validate-wiki-pointer.cjs +13 -0
  13. package/src/react/components/address/DefaultAddress.js +446 -0
  14. package/src/react/components/address/DefaultAddress.styles.js +133 -0
  15. package/src/react/components/address/DefaultAddressCoordFields.js +59 -0
  16. package/src/react/components/address/DefaultAddressMapPane.js +55 -0
  17. package/src/react/components/address/LatLonReadonlyFields.js +51 -0
  18. package/src/react/components/address/defaultAddressHelpers.js +163 -0
  19. package/src/react/components/address/defaultAddressStyles.js +148 -0
  20. package/src/react/components/address/defaultAddressUtils.js +129 -0
  21. package/src/react/components/extra-data/DefaultExtraData.js +152 -0
  22. package/src/react/components/extra-data/DefaultExtraData.styles.js +61 -0
  23. package/src/react/components/files/DefaultFile.js +231 -46
  24. package/src/react/components/files/DefaultFileColumn.js +123 -0
  25. package/src/react/components/files/DefaultFileColumn.styles.js +52 -0
  26. package/src/react/components/files/DefaultFileColumn.utils.js +104 -0
  27. package/src/react/components/filters/CompactFilterSelector.js +51 -35
  28. package/src/react/components/filters/DefaultColumnFilter.js +60 -48
  29. package/src/react/components/filters/DefaultExternalFilters.js +324 -265
  30. package/src/react/components/filters/filterValue.js +65 -0
  31. package/src/react/components/form/DefaultForm.js +99 -79
  32. package/src/react/components/help/DefaultTooltip.js +48 -12
  33. package/src/react/components/help/DefaultTooltip.styles.js +20 -0
  34. package/src/react/components/inputs/DefaultColorInput.js +153 -0
  35. package/src/react/components/inputs/DefaultFeatherIconPicker.js +146 -0
  36. package/src/react/components/inputs/DefaultFeatherIconPicker.styles.js +113 -0
  37. package/src/react/components/inputs/DefaultInput.js +296 -141
  38. package/src/react/components/inputs/DefaultInput.styles.js +26 -0
  39. package/src/react/components/inputs/DefaultSelect.js +134 -123
  40. package/src/react/components/inputs/defaultInputUtils.js +262 -213
  41. package/src/react/components/map/DefaultMap.native.js +73 -73
  42. package/src/react/components/map/DefaultMap.shared.js +911 -762
  43. package/src/react/components/map/DefaultMap.web.js +124 -68
  44. package/src/react/components/table/DefaultColumnMenu.js +22 -3
  45. package/src/react/components/table/DefaultDebug.js +44 -37
  46. package/src/react/components/table/DefaultSearchModal.js +9 -1
  47. package/src/react/components/table/DefaultTable.grouping.js +98 -0
  48. package/src/react/components/table/DefaultTable.js +217 -111
  49. package/src/react/components/table/DefaultTable.styles.js +369 -310
  50. package/src/react/components/table/DefaultTable.utils.js +38 -4
  51. package/src/react/components/table/DefaultTableBody.js +13 -8
  52. package/src/react/components/table/DefaultTableCards.js +20 -1
  53. package/src/react/components/table/DefaultTableControls.js +180 -205
  54. package/src/react/components/table/DefaultTableImportModal.js +108 -0
  55. package/src/react/components/table/DefaultTableInput.js +1 -0
  56. package/src/react/components/table/DefaultTableRowActions.js +1 -1
  57. package/src/react/components/table/DefaultTableRows.js +357 -325
  58. package/src/react/components/table/DefaultTableSearch.js +28 -5
  59. package/src/react/components/table/DefaultTableToolbar.js +92 -3
  60. package/src/react/components/table/useDefaultTablePagination.js +56 -7
  61. package/src/react/components/table/useDefaultTableStoreSync.js +164 -0
  62. package/src/react/components/upload/DefaultUpload.js +406 -0
  63. package/src/react/components/upload/DefaultUpload.styles.js +153 -0
  64. package/src/react/components/upload/DefaultUploadAttachmentsList.js +146 -0
  65. package/src/react/components/upload/DefaultUploadManagerModal.js +247 -0
  66. package/src/react/components/upload/defaultUploadHelpers.js +108 -0
  67. package/src/react/components/upload/defaultUploadLibrary.js +248 -0
  68. package/src/react/components/upload/fileUpload.js +93 -0
  69. package/src/react/hooks/usePostalCodeLookup.js +159 -0
  70. package/src/react/index.js +6 -0
  71. package/src/react/services/addressFormUtils.js +262 -0
  72. package/src/react/services/addressGeo.js +230 -0
  73. package/src/react/utils/tableVisibleColumnsPreferences.js +113 -15
  74. package/src/tests/react/components/address/defaultAddressHelpers.test.js +104 -0
  75. package/src/tests/react/components/files/DefaultFile.test.js +22 -6
  76. package/src/tests/react/components/files/DefaultFileColumn.company.test.js +24 -0
  77. package/src/tests/react/components/form/DefaultForm.test.js +123 -0
  78. package/src/tests/react/components/help/DefaultTooltip.test.js +93 -0
  79. package/src/tests/react/components/inputs/DefaultSelect.test.js +108 -79
  80. package/src/tests/react/components/table/DefaultTable.grouping.test.js +49 -0
  81. package/src/tests/react/components/table/DefaultTable.test.js +53 -2
  82. package/src/tests/react/components/table/DefaultTable.utils.test.js +10 -0
  83. package/src/tests/react/components/table/DefaultTableControls.filters.test.mjs +21 -0
  84. package/src/tests/react/components/table/DefaultTableRowActions.test.js +23 -0
  85. package/src/tests/react/components/table/DefaultTableRows.rowActions.test.js +152 -0
  86. package/src/tests/react/components/table/resolveRowBackgroundColor.test.mjs +45 -0
  87. package/src/tests/react/components/table/useDefaultTableStoreSync.test.js +161 -0
  88. package/src/tests/react/components/upload/DefaultUpload.test.js +353 -0
  89. package/src/tests/react/components/upload/defaultUploadLibrary.test.js +104 -0
  90. package/src/tests/react/components/upload/peopleMediaLibraryPreview.test.mjs +57 -0
  91. package/src/tests/react/filters/filterValue.test.js +46 -0
  92. package/src/tests/react/hooks/usePostalCodeLookup.test.js +107 -0
  93. package/src/tests/react/inputs/defaultInputUtils.test.js +9 -1
  94. package/src/tests/react/services/SMOKE-637-cep-hydrate.md +45 -0
  95. package/src/tests/react/services/addressFormUtils.test.js +179 -0
  96. package/src/tests/react/services/addressGeoLookup.async.test.js +104 -0
  97. package/src/tests/react/services/addressGeoLookup.test.js +105 -0
  98. package/src/tests/react/services/smoke-637/form-cep-12941040.png +0 -0
  99. package/src/tests/react/services/smoke-637/index.html +132 -0
  100. package/src/tests/react/utils/tableVisibleColumnsPreferences.test.js +96 -49
@@ -0,0 +1,272 @@
1
+ # DefaultTable
2
+
3
+ Componente orquestrador de listagens genéricas em React Native / RN Web.
4
+
5
+ **Arquivo:** `src/react/components/table/DefaultTable.js`
6
+ **Composição:** `DefaultTableToolbar` → `DefaultTableBody` → `DefaultTableFooter` (+ botões de add)
7
+
8
+ ## Responsabilidade
9
+
10
+ 1. Resolver **colunas** (store ou prop).
11
+ 2. Em **autoMode** (`data === undefined` e `storeName` preenchido), paginar/ordenar/filtrar via `store.actions`.
12
+ 3. Publicar um objeto **`configs`** no store para filhos lerem sem prop-drilling.
13
+ 4. Persistir preferências (colunas visíveis, filtros, view mode, sort) por escopo **empresa / store / rota**.
14
+
15
+ ## Auto mode vs dados controlados
16
+
17
+ | Modo | Condição | Comportamento |
18
+ | --- | --- | --- |
19
+ | **autoMode** | `data === undefined` e `storeName` não vazio | Pagination hook chama actions do store; `items` / `totalItems` vêm do store |
20
+ | **Controlado** | `data` é array | `items` do store são sobrescritos com `data`; refresh/endReached podem ser callbacks externos |
21
+
22
+ ## Props (principais)
23
+
24
+ | Prop | Tipo / default | Função |
25
+ | --- | --- | --- |
26
+ | `storeName` | string | Nome do store (`useStore`) |
27
+ | `columns` | array | Fallback se `store.getters.columns` vazio |
28
+ | `data` | array \| undefined | Dados controlados; `undefined` ativa autoMode |
29
+ | `actions` | object | Merge sobre `store.actions` |
30
+ | `filters` | object | Filtros iniciais / seed |
31
+ | `requestParams` | object | Params extras em toda request |
32
+ | `pageSize` | number \| null | Tamanho de página |
33
+ | `sort` | `{ field, direction }` \| null | Sort controlado |
34
+ | `onSortChange` | fn | Callback de sort |
35
+ | `hasMore` / `onEndReached` | | Infinite scroll |
36
+ | `isLoading` / `onRefresh` | | Pull-to-refresh |
37
+ | `initialViewMode` | `'table'` \| `'cards'` | Preferência inicial |
38
+ | `forceCardsOnCompact` | true | Cards quando `width <= compactBreakpoint` |
39
+ | `compactBreakpoint` | 768 | Breakpoint de compactação |
40
+ | `showToolbar` / `showSearch` / `showRowActions` | | UI chrome |
41
+ | `showColumnFiltersButton` | true | Botão de filtros de coluna |
42
+ | `add` / `onAdd` / `addLabel` / `addButtonPlacement` | | `'toolbar'` \| `'bottom'` \| `'floating'` |
43
+ | `importAction` / `onImport` / `exportAction` / `onExport` | | Import/export |
44
+ | `onRowPress` / `onEditRow` / `onSaved` | | Interação de linha |
45
+ | `rowActionsComponent` / `rowActionsWidth` / `pinRowActions` | | Ações por linha |
46
+ | `renderCard` / `cardListProps` | | Customização de cards |
47
+ | `summary` / `summaryLabels` | | Rodapé agregado |
48
+ | `footerComponent` | | Slot de footer |
49
+ | `toolbarActions` | array | Ações extras na toolbar |
50
+ | `getOptionsForColumn` | fn | Options locais para selects |
51
+ | `searchKey` | `'search'` | Param de busca textual |
52
+ | `searchPlaceholder` | string | Placeholder |
53
+ | `visibleColumnsPreferenceKey` | string | Chave extra de preferência |
54
+ | `accentColor` / `defaultColor` | | Tema / cor padrão de campos cor |
55
+ | `rowStyle` | | Estilo por linha |
56
+
57
+ ## Contrato do store
58
+
59
+ Esperado em `useStore(storeName)`:
60
+
61
+ | Getter / action | Uso |
62
+ | --- | --- |
63
+ | `getters.columns` | Definição de colunas (preferencial) |
64
+ | `getters.items` | Linhas |
65
+ | `getters.totalItems` | Paginação |
66
+ | `getters.filters` | Filtros ativos |
67
+ | `getters.visibleColumns` | Mapa de colunas visíveis |
68
+ | `getters.configs` | Publicado pelo `DefaultTable` para filhos |
69
+ | `getters.add` | Se `true`, habilita add com `actions.save` ou `onAdd` |
70
+ | `actions.getItems` (ou equivalente na paginação) | Load |
71
+ | `actions.save` | Persistência (form/inline) |
72
+ | `actions.setColumns` / `setItems` / `setFilters` / `setVisibleColumns` / `setConfigs` | Preferidos; senão muta getters |
73
+
74
+ Helpers de publicação interna: `publishStoreValue` / `assignGetterValue`.
75
+
76
+ ### Objeto `configs` (publicação)
77
+
78
+ O table monta `defaultTableConfigs` e grava em `store.getters.configs`, incluindo: view mode efetivo, sort resolvido, callbacks de refresh/endReached, flags de UI, `sortedData`, `debugFallbackParameters`, preferência scope, etc. Filhos (`Toolbar`, `Body`, `Footer`) leem **só** `storeName` e usam `configs`.
79
+
80
+ ## View modes
81
+
82
+ 1. Preferência persistida (`resolveStoredTableViewModePreference`)
83
+ 2. `configs.viewMode` corrente
84
+ 3. Compacto: se `width <= compactBreakpoint` e `forceCardsOnCompact`, força `'cards'`
85
+ 4. Senão `initialViewMode` (default `'table'`)
86
+
87
+ `DefaultTableBody` escolhe `DefaultTableRows` vs `DefaultTableCards`.
88
+
89
+ ## Preferências persistidas (escopo por empresa)
90
+
91
+ Escopo via `resolveDefaultTablePreferenceScope({ companyId, preferenceKey, route, storeName })`.
92
+
93
+ Estrutura no `localStorage` (chave raiz `default-table`):
94
+
95
+ ```text
96
+ default-table[companyKey][storeKey][routeKey] = {
97
+ visibleColumns,
98
+ filters,
99
+ viewMode,
100
+ sort
101
+ }
102
+ ```
103
+
104
+ - `companyKey` = identificador estável da empresa ativa (normalizado).
105
+ - `storeKey` = nome do store (`storeName`).
106
+ - `routeKey` = `preferenceKey` explícito, pathname, `route.name` ou `route.key`.
107
+
108
+ **O que é persistido:** colunas visíveis, filtros de tabela, view mode e sort.
109
+
110
+ **Sanitização:** `sanitizeVisibleColumnsPreference` / `sanitizeTableFiltersPreference` (só campos de colunas filtráveis + `search`; ignora chaves desconhecidas ou bloqueadas com `filter: false`).
111
+
112
+ ### Comportamento na troca de empresa
113
+
114
+ 1. O escopo muda (`companyKey` novo).
115
+ 2. Filtros, colunas, sort e view mode da empresa anterior **não** são reutilizados.
116
+ 3. O table hidrata as preferências salvas para a nova empresa (ou defaults se não houver).
117
+ 4. Listas/opções de filtros (selects de coluna e filtros externos) devem ser **recarregadas** no contexto da empresa ativa — não reutilizar opções carregadas para a empresa anterior.
118
+ 5. Stores e rotas diferentes continuam isolados entre si.
119
+
120
+ **Compatibilidade com formato legado:** preferências antigas no formato `default-table[store][route]` (sem `companyKey`) **não** são copiadas automaticamente para todas as empresas. Escopos sem `companyKey` são ignorados na leitura/gravação (ver testes em `tableVisibleColumnsPreferences.test.js`).
121
+
122
+ Referência de implementação: `src/react/utils/tableVisibleColumnsPreferences.js`.
123
+
124
+ ## Paginação e sort
125
+
126
+ - `useDefaultTablePagination` — monta query (`buildRequestQuery`), página corrente, refresh, end reached
127
+ - `useDefaultTableSortState` / `useDefaultTableSortedData` — sort remoto/local
128
+ - Utils: `resolveDefaultSort`, `isSortableColumn`, `getSortField`, `mergeSortedDataWithLiveItems`
129
+
130
+ Constantes úteis (`DefaultTable.utils.js`):
131
+
132
+ - `DEFAULT_COMPACT_BREAKPOINT = 768`
133
+ - `END_REACHED_THRESHOLD = 0.75`
134
+ - larguras mínimas de célula (identity / money / default)
135
+
136
+ ## Composição interna
137
+
138
+ | Peça | Papel |
139
+ | --- | --- |
140
+ | `DefaultTableToolbar` | Search, controles, import modal, ações |
141
+ | `DefaultTableControls` | Column menu, filters modal, debug |
142
+ | `DefaultTableSearch` / `DefaultSearchModal` | Busca (compacta ou modal) |
143
+ | `DefaultTableRows` | Cabeçalho, filtros por coluna, células, inline edit |
144
+ | `DefaultTableCards` | Layout card + `renderCard` opcional |
145
+ | `DefaultTableInput` | Ponte célula → `DefaultInput` |
146
+ | `DefaultTableFooter` | Totais / summary / paginação visual |
147
+ | `DefaultTableEmptyState` | Empty + `StateStore` |
148
+ | `DefaultTableRowActions` | Slot de ações |
149
+ | `useDefaultTableTheme` | Cores de painel/borda/botão a partir do theme store |
150
+
151
+ ## Fluxo de dados (autoMode)
152
+
153
+ ```mermaid
154
+ sequenceDiagram
155
+ participant T as DefaultTable
156
+ participant P as useDefaultTablePagination
157
+ participant S as Store
158
+ participant API as Backend
159
+ T->>P: buildRequestQuery(page)
160
+ P->>S: actions.getItems(params)
161
+ S->>API: HTTP
162
+ API-->>S: items + totalItems
163
+ S-->>T: getters.items
164
+ T->>T: sortedData + configs
165
+ T->>T: Body/Footer render
166
+ ```
167
+
168
+ ## Integração mínima
169
+
170
+ ```jsx
171
+ <DefaultTable
172
+ storeName="customers"
173
+ onAdd={() => openCreateModal()}
174
+ onRowPress={(row) => openDetails(row)}
175
+ />
176
+ ```
177
+
178
+ Com colunas só via prop (store ainda sem columns):
179
+
180
+ ```jsx
181
+ <DefaultTable
182
+ storeName="customers"
183
+ columns={[
184
+ { name: 'id', label: 'ID', isIdentity: true, editable: false },
185
+ { name: 'name', label: 'Nome', editable: true },
186
+ { name: 'status', label: 'Status', list: 'status/getItems', editable: true },
187
+ ]}
188
+ />
189
+ ```
190
+
191
+
192
+ ## Sincronização com o store (`useDefaultTableStoreSync`)
193
+
194
+ Hook interno que mantém props controladas do `DefaultTable` alinhadas ao slice Zustand **sem depender da identidade do objeto `store`** (Zustand troca a referência a cada commit).
195
+
196
+ **Arquivo:** `src/react/components/table/useDefaultTableStoreSync.js`
197
+ **Testes:** `src/tests/react/components/table/useDefaultTableStoreSync.test.js`
198
+
199
+ ### O que sincroniza
200
+
201
+ | Efeito | Origem → destino | Guard anti-loop |
202
+ | --- | --- | --- |
203
+ | Colunas | prop `columns` → `actions.setColumns` / `getters.columns` | só se o store ainda não tiver colunas |
204
+ | Itens controlados | prop `data` → `actions.setItems` | mesma referência de array (`lastPublishedItemsRef`) |
205
+ | Colunas visíveis | `localStorage` (escopo empresa/store/rota) → `setVisibleColumns` | sanitização por colunas atuais |
206
+ | Filtros persistidos | `localStorage` → `setFilters` | **hydrate uma vez por scopeKey** + `areTableFiltersEqual` |
207
+ | Configs | `defaultTableConfigs` → `setConfigs` | assinatura estável (`defaultTableConfigsSignature`) |
208
+
209
+ Helpers exportados: `publishStoreValue`, `assignGetterValue`, `areTableFiltersEqual`.
210
+
211
+ ### Preferências de filtro — regra de hydrate único
212
+
213
+ Filtros de tabela são lidos de `resolveStoredTableFiltersPreference(tablePreferenceScope)` e aplicados via `sanitizeTableFiltersPreference`.
214
+
215
+ **`scopeKey`** (estável):
216
+
217
+ ```text
218
+ companyKey :: storeKey :: routeKey :: colunas(key|name)|...
219
+ ```
220
+
221
+ Regras canônicas (app-community#448 / ui-orders OrderHistoryPage):
222
+
223
+ 1. Hydrate de filtros persistidos ocorre **no máximo uma vez** por `scopeKey` (`lastHydratedFiltersKeyRef`).
224
+ 2. **Não** reagir a mudanças de `storeFilters` após o hydrate — perseguir o store recria o payload e gera React **#185** (Maximum update depth exceeded).
225
+ 3. Antes de `setFilters`, comparar com `areTableFiltersEqual` (JSON estável). Se já for equivalente, só marca o `scopeKey` e sai.
226
+ 4. Toggle típico que quebrava: período `today → all → today` em `OrderHistoryPage` (filtro externo de data + DefaultTable). O guard em `useOrderHistoryFilters` (`areHistoryFiltersEqual`) **não basta** se o loop nascer no hydrate do DefaultTable.
227
+
228
+ ```mermaid
229
+ flowchart TD
230
+ A[DefaultTable mount / columns ready] --> B{stored filters?}
231
+ B -->|não| C[marca scopeKey]
232
+ B -->|sim| D[sanitize]
233
+ D --> E{scopeKey já hydrated?}
234
+ E -->|sim| F[return — não chase storeFilters]
235
+ E -->|não| G{areTableFiltersEqual?}
236
+ G -->|sim| C
237
+ G -->|não| H[setFilters + marca scopeKey]
238
+ ```
239
+
240
+ ### Por que não colocar `storeFilters` nas deps
241
+
242
+ Incluir `storeFilters` no array de dependências do efeito de hydrate faz:
243
+
244
+ `setFilters` → nova referência no store → efeito roda de novo → `setFilters` → **#185**.
245
+
246
+ A correção remove `storeFilters` das deps e usa `storeFiltersRef` só para a comparação de igualdade no momento do hydrate.
247
+
248
+ ### Visões (`APP_TYPE`)
249
+
250
+ `ui-default` **não** conhece domínio de pedido/CRM/POS. Qualquer tela que use `DefaultTable` + filtros de período (ex.: histórico de pedidos em `ui-orders`, listagens CRM) herda este contrato. O módulo consumidor não deve reaplicar filtros persistidos em todo change do store; o orquestrador já faz o hydrate único.
251
+
252
+ ### Testes mínimos esperados
253
+
254
+ - Publicação de `data` uma vez por referência de array (Devices / #185 histórico).
255
+ - Hydrate de filtros uma vez; após churn de `storeFilters` (simular today→all→today), `setFilters` continua 1×.
256
+ - `areTableFiltersEqual` trata payloads de período equivalentes como iguais.
257
+
258
+ ## Limites e cuidados
259
+
260
+ - Filhos dependem de `configs` no store: não renderize Body isolado sem o orquestrador.
261
+ - Preferências são por **empresa + store + rota**: mudou empresa ou rota, o escopo muda.
262
+ - `stableSerialize` evita loops de `setConfigs`.
263
+ - Hydrate de filtros persistidos é **único por scopeKey** — não recoloque `storeFilters` nas deps do efeito de hydrate (React #185; ver seção `useDefaultTableStoreSync`).
264
+ - List stores com escopo de empresa (`categories`, `paymentType`, `wallet`) recebem `company`/`people` automaticamente nos loads de select/coluna.
265
+
266
+ ## Arquivos relacionados
267
+
268
+ - `DefaultTable.js`, `DefaultTable.utils.js`, `DefaultTable.styles.js`
269
+ - Hooks: `useDefaultTablePagination.js`, `useDefaultTableSorting.js`, `useDefaultTableTheme.js`, **`useDefaultTableStoreSync.js`**
270
+ - Preferências: `src/react/utils/tableVisibleColumnsPreferences`
271
+ - Testes: `src/tests/react/utils/tableVisibleColumnsPreferences.test.js`
272
+ - Testes store sync: `src/tests/react/components/table/useDefaultTableStoreSync.test.js`
package/docs/wiki.md ADDED
@@ -0,0 +1 @@
1
+ https://github.com/ControleOnline/ui-default/wiki
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@controleonline/ui-default",
3
- "version": "1.0.270",
3
+ "version": "1.0.273",
4
4
  "author": "ControleOnline",
5
5
  "description": "ControleOnline Default Quasar UI Component",
6
6
  "license": "MIT",
@@ -8,7 +8,7 @@
8
8
  "scripts": {},
9
9
  "repository": {
10
10
  "type": "git",
11
- "url": "https://github.com/ControleOnline/conline-quasar-ui"
11
+ "url": "https://github.com/ControleOnline/ui-default"
12
12
  },
13
13
  "bugs": "",
14
14
  "homepage": "https://www.controleonline.com/devs/plugins",
@@ -16,6 +16,7 @@
16
16
  "last 1 version, not dead, ie >= 11"
17
17
  ],
18
18
  "dependencies": {
19
- "@controleonline/ui-common": "*"
19
+ "@controleonline/ui-common": "*",
20
+ "react-native-vector-icons": "^10.3.0"
20
21
  }
21
22
  }
@@ -0,0 +1,13 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const root = path.resolve(__dirname, '..');
4
+ const repo = path.basename(root);
5
+ const pointer = fs.readFileSync(path.join(root, 'docs/wiki.md'), 'utf8');
6
+ const expected = `https://github.com/ControleOnline/${repo}/wiki\n`;
7
+ if (pointer !== expected) throw new Error(`docs/wiki.md must contain only ${expected.trim()}`);
8
+ const gitmodulesPath = path.join(root, '.gitmodules');
9
+ if (fs.existsSync(gitmodulesPath)) {
10
+ const gitmodules = fs.readFileSync(gitmodulesPath, 'utf8');
11
+ if (/path\s*=\s*docs\/wiki/.test(gitmodules) || new RegExp(`${repo}\\.wiki\\.git`).test(gitmodules)) throw new Error('docs/wiki must not be configured as a wiki submodule');
12
+ }
13
+ console.log(`Validated wiki pointer for ${repo}.`);