pgkiln 0.71.0 → 0.73.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/db/migrations/139_opentelemetry.sql +36 -0
- package/db/migrations/140_item_region_types.sql +27 -0
- package/docs/apex-feature-parity.md +86 -9
- package/docs/guide/01-installation.md +108 -0
- package/docs/guide/03-builder.md +9 -0
- package/docs/guide/04-pages-and-regions.md +41 -1
- package/docs/guide/05-items.md +43 -3
- package/docs/guide/09-reference.md +3 -0
- package/docs/guide/11-from-apex.md +3 -0
- package/docs/guide/12-development.md +23 -2
- package/examples/hr/hr_75_item_region_types.sql +81 -0
- package/package.json +1 -1
- package/public/app.css +48 -0
- package/public/app.js +427 -1
- package/public/builder.css +3 -0
- package/src/ai/service.ts +14 -0
- package/src/app.ts +10 -0
- package/src/builder/advisor.ts +5 -1
- package/src/builder/arrange.ts +7 -0
- package/src/builder/components.ts +5 -5
- package/src/builder/designer.ts +8 -2
- package/src/builder/home.ts +1 -0
- package/src/builder/i18n/de.ts +8 -0
- package/src/builder/i18n/en.ts +8 -0
- package/src/builder/i18n/es.ts +8 -0
- package/src/builder/i18n/fr.ts +8 -0
- package/src/builder/i18n/it.ts +8 -0
- package/src/builder/i18n/ja.ts +8 -0
- package/src/builder/i18n/ko.ts +8 -0
- package/src/builder/i18n/nl.ts +8 -0
- package/src/builder/i18n/pt.ts +8 -0
- package/src/builder/i18n/zh-cn.ts +8 -0
- package/src/builder/i18n/zh-tw.ts +8 -0
- package/src/builder/region-help.ts +8 -2
- package/src/builder/telemetry.ts +206 -0
- package/src/builder/workspaces.ts +2 -1
- package/src/i18n/ar.ts +13 -0
- package/src/i18n/cs.ts +13 -0
- package/src/i18n/da.ts +13 -0
- package/src/i18n/de.ts +13 -0
- package/src/i18n/el.ts +13 -0
- package/src/i18n/es.ts +13 -0
- package/src/i18n/fi.ts +13 -0
- package/src/i18n/fr.ts +13 -0
- package/src/i18n/he.ts +13 -0
- package/src/i18n/it.ts +13 -0
- package/src/i18n/ja.ts +13 -0
- package/src/i18n/ko.ts +13 -0
- package/src/i18n/nb.ts +13 -0
- package/src/i18n/pl.ts +13 -0
- package/src/i18n/pt.ts +13 -0
- package/src/i18n/ru.ts +13 -0
- package/src/i18n/sv.ts +13 -0
- package/src/i18n/tr.ts +13 -0
- package/src/i18n/uk.ts +13 -0
- package/src/i18n/zh.ts +13 -0
- package/src/i18n.ts +26 -0
- package/src/instance-checks.ts +11 -4
- package/src/layout.ts +2 -1
- package/src/mail/mail.ts +14 -0
- package/src/metadata.ts +5 -2
- package/src/runtime/ai-agents.ts +9 -0
- package/src/runtime/items.ts +32 -3
- package/src/runtime/page-regions.ts +50 -0
- package/src/runtime/region-cache.ts +1 -1
- package/src/runtime/regions.ts +11 -0
- package/src/runtime/render.ts +3 -17
- package/src/runtime/report.ts +55 -3
- package/src/runtime/routes.ts +3 -0
- package/src/session.ts +26 -0
- package/src/telemetry/browser.ts +91 -0
- package/src/telemetry/config.ts +342 -0
- package/src/telemetry/export.ts +484 -0
- package/src/telemetry/http.ts +126 -0
- package/src/telemetry/trace.ts +456 -0
- package/src/webclient.ts +25 -0
- package/src/workflow.ts +14 -7
|
@@ -649,6 +649,9 @@ pgkiln's icons; its filter box also searches the Lucide icons by name and search
|
|
|
649
649
|
| `GET/POST /a/:alias/account`, `POST /a/:alias/account/password`, `POST /a/:alias/account/theme`, `POST /a/:alias/account/style` | My account, own password, the light/dark switch, the [style variant](14-globalization.md#style-variants-theme-roller) switch |
|
|
650
650
|
| `POST /a/:alias/tz` | The browser's time zone for the session (automatic time zone; sent by `app.js`, CSRF token required) |
|
|
651
651
|
| any page `?lang=xx` | Switch the language for the session |
|
|
652
|
+
| `POST /a/:alias/telemetry` | (0.72) Browser spans of a page whose trace goes to an OpenTelemetry collector (sent by `app.js`; a signed token of the page, 204) |
|
|
653
|
+
| `GET /metrics` | (0.72) Metrics in the Prometheus text format, when switched on: an administrator's builder session or `Authorization: Bearer <metrics token>` ([chapter 1](01-installation.md#monitoring-with-opentelemetry)) |
|
|
654
|
+
| `GET /healthz` | `ok` when the database is reachable (503 otherwise) |
|
|
652
655
|
| `/builder/...` | Builder |
|
|
653
656
|
| PostgREST (separate service, `API_URL`) | REST API of each app's `api` schema, see [chapter 13](13-rest-api.md) |
|
|
654
657
|
| `/static/...` | CSS, JavaScript, icons |
|
|
@@ -59,6 +59,9 @@ What's missing is listed in the [feature parity matrix](../apex-feature-parity.m
|
|
|
59
59
|
| `APEX_DATA_EXPORT.EXPORT` | `meta.data_export(query, format, options)` (CSV, JSON, XML, HTML) and the download process's `{"export": "xlsx"}` (also PDF) ([chapter 6](06-processing.md#data-export-from-sql)) |
|
|
60
60
|
| `APEX_LANG.LANG`, dynamic translations | Shared Components → Dynamic translations and `meta.lang(text)` ([chapter 14](14-globalization.md#dynamic-translations)) |
|
|
61
61
|
| Display Image, Geocoded Address items | Item types `image` and `address` (geocoder: `GEOCODER_URL`) ([chapter 5](05-items.md#display-image-and-geocoded-address)) |
|
|
62
|
+
| Shuttle, Select One, Select Many (24.2) items | Item types `shuttle` (ordered, colon-separated), `select_one` and `select_many` (a search field over the list of values; chips): plain selects without JavaScript ([chapter 5](05-items.md#shuttle-select-one-and-select-many)) |
|
|
63
|
+
| Classic Report region (report templates, pagination types) | Region type `classic_report`: `report_template` `standard`, `value_pairs`, `badges` or `media_list`; `pagination` `total`, `range` or `none` ([chapter 4](04-pages-and-regions.md#classic_report-classic-report)) |
|
|
64
|
+
| Breadcrumb region (Breadcrumb Bar), Help Text region and page help | Region types `breadcrumb` (from each page's *Breadcrumb parent*; no separate breadcrumb shared component) and `help_text`; the page's *Help text* (Markdown) ([chapter 4](04-pages-and-regions.md#breadcrumb-and-help_text)) |
|
|
62
65
|
| Translated applications (XLIFF), `APEX_LANG.MESSAGE`, `&APP_TEXT$NAME.` | Translations in the app (XLIFF/CSV import and export), `meta.message()`, `&APP_TEXT$NAME.` ([chapter 14](14-globalization.md)) |
|
|
63
66
|
| Application date format mask | Settings → Globalization → Date format (Oracle-style masks) |
|
|
64
67
|
| Number format masks (`FML999G999G990D00`) on columns and items | `{"formats": {...}}` on report, grid and cards columns, `{"format_mask": "..."}` on charts and number/display items ([chapter 14](14-globalization.md#number-formats)) |
|
|
@@ -190,6 +190,16 @@ src/
|
|
|
190
190
|
debug.ts debug messages: DebugLog (levels, timed steps, NOTICEs of meta.debug from appTx), started in
|
|
191
191
|
loadContext, stored after the response (onResponse hook → meta.debug_save), hourly purge
|
|
192
192
|
icons.ts icon helper (sprite in public/icons.svg)
|
|
193
|
+
telemetry/ (sprint 139, AP-6) OpenTelemetry without the SDK: trace.ts (the current trace in AsyncLocalStorage,
|
|
194
|
+
startTrace/endTrace, withSpan/rootSpan/recordSpan, traceApp, traceparent, a span per statement by
|
|
195
|
+
patching pg.Client#query, sanitizeSql/redactText, counters and histograms), config.ts (the instance's
|
|
196
|
+
settings: meta.setting otel_* over OTEL_* variables; workspaces' telemetry columns; app → workspace,
|
|
197
|
+
cached 30 s), export.ts (a queue per collector, OTLP/HTTP JSON for traces, logs and metrics, values
|
|
198
|
+
only where included, gauges from the queues, prometheusText(), sendTest()), http.ts (a trace per
|
|
199
|
+
request, request metrics, GET /metrics, POST /a/:alias/telemetry), browser.ts (the page's signed
|
|
200
|
+
<meta name="pgkiln-trace"> in layout.ts and relay() of what app.js reports). Spans come from
|
|
201
|
+
webclient.ts (outgoing calls, traceparent), ai/service.ts logUsage, runtime/ai-agents.ts logToolCall,
|
|
202
|
+
mail/mail.ts sendOne, workflow.ts runWorkflow; logs from session.ts logActivity
|
|
193
203
|
history.ts (sprint 138, AP-5) change history and checksums: meta.app_snapshot (the export after the last recorded
|
|
194
204
|
change), recordHistory() (export again, workingcopy.ts components() of both, each added/changed/deleted
|
|
195
205
|
component with its files before and after into meta.component_change; called by app-updates.ts onSend,
|
|
@@ -211,6 +221,8 @@ src/
|
|
|
211
221
|
logic.ts computations (the page's and (102) the application's), branches (page, URL, function returning a URL, another application) and their conditions
|
|
212
222
|
shortcuts.ts (103) "NAME" shortcuts in static content, help texts and confirm messages
|
|
213
223
|
render.ts page chrome (nav, breadcrumb), dynamic action JSON, theme (the page's nonce'd <style>, light/dark and style switches)
|
|
224
|
+
page-regions.ts (sprint 140) breadcrumb and help_text regions: breadcrumbLinks (also the title bar's trail, left out when the
|
|
225
|
+
page has a breadcrumb region), the page's help text (meta.page.help) as Markdown with escaped &ITEM. values
|
|
214
226
|
styles.ts base styles (BASE_STYLES: Iris, Lavender, Standard; baseStyleOf → html data-style), Theme Roller style variants: fixed lists (fonts, sizes, corners), parseStyle/appStyles checks, the request's
|
|
215
227
|
style (user choice, default), themeCss() (only hex values and constants reach the CSS); (sprint 117) NAV_APPEARANCES
|
|
216
228
|
(Pillar Light / Dark), navAppearance() → the <body> classes nav-pillar-*, the header strip (--strip)
|
|
@@ -218,7 +230,10 @@ src/
|
|
|
218
230
|
regions.ts region shell + chart (drill-down links, gauge settings)/cards/dynamic dispatch with row limits, lazy placeholder and cache, buttons (menu buttons, badges; (124) menu entries {action} → data-menu-entry for menu_entry dynamic actions)
|
|
219
231
|
report.ts, report-views.ts (group by, pivot, chart), compute.ts (computed column expressions), grid.ts (aggregates, row actions, Actions menu, single row view, layoutFromForm), grid-layout.ts (column layouts: clean, arrange, per user), master-detail.ts (signed master row selection, details), facets.ts (facetChart: a facet's counts as a chart, sprint 65), items.ts
|
|
220
232
|
(report.ts: paging with row ranges and max_rows, keyset paging (keysetPlan, seekCondition, signed r<id>_k), pagerNav, streamed CSV/Excel downloads with a cursor;
|
|
221
|
-
|
|
233
|
+
(140) classic_report through renderReport: reportState drops the interactive settings, classicTemplate (value_pairs, badges, media_list),
|
|
234
|
+
pagination total/range/none;
|
|
235
|
+
items.ts: lovOptions, searchLov/lovLookup for popup LOVs, served by POST /a/:alias/:page/lov/:item/search in routes.ts;
|
|
236
|
+
LOV_TYPES / LOV_CHECKED / MULTI_VALUE: the list item types (shuttle, select_one, select_many since 140) checked on submit and colon-separated)
|
|
222
237
|
region-cache.ts region caching (keys per scope, CSRF placeholder, invalidation on submit) and lazy regions (GET …/region/:id is in routes.ts)
|
|
223
238
|
gantt-move.ts (sprint 69) Gantt drag and drop: ganttEditable, targetTime, moveGanttTask (the task in the region's
|
|
224
239
|
query, gantt_move with :TASK_ID/:NEW_START/:NEW_END); the dragging itself is in app.js
|
|
@@ -392,6 +407,9 @@ src/
|
|
|
392
407
|
vector-providers.ts (sprint 136, AP-1) Shared Components → Vector providers (/apps/:id/vector-providers: list, provider form,
|
|
393
408
|
test, delete) and Workspace utilities → Vector providers (/vector-providers: pgvector status, Create
|
|
394
409
|
extension for administrators, the workspace's providers and vector columns); pgvectorNote()
|
|
410
|
+
telemetry.ts (sprint 139, AP-6) Workspace utilities → OpenTelemetry (/telemetry: the collector, signals, values, user,
|
|
411
|
+
browser spans, /metrics and its token, status per collector, Send a test span; administrators) and a
|
|
412
|
+
workspace's own (/workspaces/:id/telemetry: as the instance / off / own collector; its administrators)
|
|
395
413
|
data-security.ts (sprint 119) a table's Security: GET/POST /sql/objects/security?o= (policies, roles × columns, masks), Preview / Apply
|
|
396
414
|
object-actions.ts (sprint 94) an object's ⋯ menu (objectMenu) in the worksheet and the Object Browser: Quick DDL (objectDdl), Drop with
|
|
397
415
|
dependents, Add index / trigger / policy as drafts; GET /sql/objects/action, /sql/objects/panel (Open in a panel)
|
|
@@ -506,7 +524,8 @@ public/
|
|
|
506
524
|
(sprint 117) navigation tree states, RTL via logical properties, body.nav-pillar-*, u-color-*-subtle, the busy bar)
|
|
507
525
|
app.js client runtime: dialogs (dialog_closed actions), popup LOVs (sprint 115: the next page loads on scroll through an
|
|
508
526
|
IntersectionObserver, ‹/More without one), dynamic actions (focus, classes, messages; sprint 115: wait_popup /
|
|
509
|
-
remove_wait_popup as a modal <dialog class="wait-popup">, pgkiln.waitPopup(), the menu_entry event),
|
|
527
|
+
remove_wait_popup as a modal <dialog class="wait-popup">, pgkiln.waitPopup(), the menu_entry event), (sprint 140) shuttle()
|
|
528
|
+
and selectPick() (Select One / Many: combobox + listbox, chips) over the item's hidden <select>, grids (add/duplicate rows, master-detail refresh, move/resize columns, copy/paste of cell ranges), menus, lazy regions, maps (Leaflet layers, marker clusters, heat layer, layer legend, area/distance filter) (no inline JS)
|
|
510
529
|
code-editor.js, .css builder code editor: enhances <textarea data-code>, highlighting, suggestions (no dependencies);
|
|
511
530
|
(sprint 108) the current line, and read-only <pre data-code-view="sql|plpgsql|json|html"> highlighted;
|
|
512
531
|
its colours are the --ce-* tokens in builder.css
|
|
@@ -532,6 +551,7 @@ test/
|
|
|
532
551
|
globalization.test.ts masks on HR page 29, time zones, the de/fr/es texts
|
|
533
552
|
files.test.ts file items: storage, limits, downloads, temporary files
|
|
534
553
|
items.test.ts rich text, Markdown, rating, combobox, date range, password reveal and QR code items
|
|
554
|
+
item-region-types.test.ts (sprint 140) shuttle, select one/many, classic report, breadcrumb and help text: gallery, runtime, export, Advisor, HR page 50
|
|
535
555
|
dataload.test.ts parsing, Load Data, the data_load process
|
|
536
556
|
sampledata.test.ts Sample Data: CHECK parsing, proposals, option errors, seeds and streams, preview/insert/rollback, parents first, downloads, saved generators
|
|
537
557
|
unload.test.ts Unload Data: CSV/JSON/XLSX/XML output, read back with Load Data, read-only and one-statement checks, streaming
|
|
@@ -628,6 +648,7 @@ test/
|
|
|
628
648
|
e2e/worksheet.test.ts (sprint 91) the SQL Worksheet in a browser: run keys, tabs, navigator, drag and drop, splitters, phone, no JavaScript;
|
|
629
649
|
(107) transaction mode: badge, reload, Rollback, closing a tab, Autocommit switch, beforeunload
|
|
630
650
|
e2e/items.test.ts sprint 26 item types in a browser: editors, tags, stars, dates, reveal; without JavaScript
|
|
651
|
+
e2e/item-region-types.test.ts (sprint 140) the shuttle (buttons, keyboard, order) and Select One / Many in a browser; without JavaScript; 390 px
|
|
631
652
|
e2e/designer.test.ts page designer: panes per width, drag and drop, keyboard, Arrange buttons, builder theme
|
|
632
653
|
e2e/calendar.test.ts calendar drag and drop and create on click, view switching, chart drill-down
|
|
633
654
|
e2e/gantt.test.ts Gantt drag and drop: moving a task, its end, the keyboard, a click still drills down, the phone
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
-- =====================================================================
|
|
2
|
+
-- HR example, part 75: the item and region types of sprint 140 (AP-4;
|
|
3
|
+
-- migration 140; docs/guide/05-items.md, 04-pages-and-regions.md)
|
|
4
|
+
--
|
|
5
|
+
-- Page 50 "Project team" (Administration → Project team) puts a team
|
|
6
|
+
-- together the way an APEX page would:
|
|
7
|
+
--
|
|
8
|
+
-- - P50_DEPTNO, a Select One (a searchable single pick) of the
|
|
9
|
+
-- departments;
|
|
10
|
+
-- - P50_MEMBERS, a Shuttle of that department's employees (a cascading
|
|
11
|
+
-- list of values: choosing another department reloads it). The chosen
|
|
12
|
+
-- employees keep their order (Move up / Move down), stored
|
|
13
|
+
-- colon-separated like a multiselect: 7839:7566:7902;
|
|
14
|
+
-- - P50_SKILLS, a Select Many (chips) of a static list of values.
|
|
15
|
+
-- Without JavaScript the three are a plain select list and two
|
|
16
|
+
-- multi-selection lists, and Save works the same;
|
|
17
|
+
-- - "Chosen team", a Classic Report (no Actions menu) of the chosen
|
|
18
|
+
-- employees in the shuttle's order, and "Head count", a classic report
|
|
19
|
+
-- with the badges template;
|
|
20
|
+
-- - a Breadcrumb region in the Breadcrumb bar position (the title bar
|
|
21
|
+
-- then leaves its own trail out), and a Help Text region showing the
|
|
22
|
+
-- page's help text (Page → Help text, Markdown).
|
|
23
|
+
-- Save keeps the values in the session only: the page has no table.
|
|
24
|
+
-- =====================================================================
|
|
25
|
+
|
|
26
|
+
insert into meta.page (app_id, page_no, name, title, parent_page, help)
|
|
27
|
+
select id, 50, 'Project team', 'Project team', 1,
|
|
28
|
+
$h$Put a **project team** together:
|
|
29
|
+
|
|
30
|
+
1. Choose a *department* (type to search the list).
|
|
31
|
+
2. Move its employees from **Available** to **Selected** (double-click, Enter, or the › and » buttons) and put them in order with the arrow buttons.
|
|
32
|
+
3. Choose the skills the team needs, then **Save**.
|
|
33
|
+
|
|
34
|
+
Team lead for now: &APP_USER..$h$
|
|
35
|
+
from meta.app where alias = 'hr';
|
|
36
|
+
|
|
37
|
+
insert into meta.region (page_id, seq, title, type, columns, template, position, source, config)
|
|
38
|
+
select p.id, r.seq, r.title, r.type, r.cols, r.template, r.position, r.source, r.config::jsonb
|
|
39
|
+
from meta.page p join meta.app a on a.id = p.app_id, (values
|
|
40
|
+
(5, 'Breadcrumb', 'breadcrumb', 12, 'plain', 'breadcrumb', null, '{}'),
|
|
41
|
+
(10, 'Team', 'static', 8, 'standard', null, null, '{}'),
|
|
42
|
+
(20, 'How it works', 'help_text', 4, 'standard', null, null, '{}'),
|
|
43
|
+
(30, 'Chosen team', 'classic_report', 8, 'standard', null,
|
|
44
|
+
'select e.empno, e.ename, e.job, d.dname
|
|
45
|
+
from unnest(string_to_array(:P50_MEMBERS, '':'')) with ordinality m(empno, n)
|
|
46
|
+
join hr.emp e on e.empno::text = m.empno
|
|
47
|
+
left join hr.dept d on d.deptno = e.deptno
|
|
48
|
+
order by m.n',
|
|
49
|
+
'{"headings": {"empno": "No.", "ename": "Name", "job": "Job", "dname": "Department"}, "sortable": false, "pagination": "none", "empty": "Nobody chosen yet: move employees to Selected and save."}'),
|
|
50
|
+
(40, 'Head count', 'classic_report', 4, 'standard', null,
|
|
51
|
+
'select d.dname as label, count(e.empno) as value
|
|
52
|
+
from hr.dept d left join hr.emp e on e.deptno = d.deptno
|
|
53
|
+
group by d.dname order by d.dname',
|
|
54
|
+
'{"report_template": "badges", "pagination": "none"}')
|
|
55
|
+
) as r (seq, title, type, cols, template, position, source, config)
|
|
56
|
+
where a.alias = 'hr' and p.page_no = 50;
|
|
57
|
+
|
|
58
|
+
insert into meta.item (page_id, region_id, seq, name, label, type, lov, config, help)
|
|
59
|
+
select p.id, r.id, i.seq, i.name, i.label, i.type, i.lov, i.config::jsonb, i.help
|
|
60
|
+
from meta.page p join meta.app a on a.id = p.app_id
|
|
61
|
+
join meta.region r on r.page_id = p.id and r.title = 'Team', (values
|
|
62
|
+
(10, 'P50_DEPTNO', 'Department', 'select_one', 'select dname, deptno from hr.dept order by 1', '{"wide": true}', null),
|
|
63
|
+
(20, 'P50_MEMBERS', 'Team members', 'shuttle',
|
|
64
|
+
'select ename || '' ('' || coalesce(job, ''-'') || '')'' as d, empno as r from hr.emp where deptno = :P50_DEPTNO order by ename',
|
|
65
|
+
'{"cascade_parents": "P50_DEPTNO", "wide": true}', 'In the order they lead the project.'),
|
|
66
|
+
(30, 'P50_SKILLS', 'Skills needed', 'select_many',
|
|
67
|
+
'STATIC:SQL;SQL,PL/pgSQL;PLPGSQL,TypeScript;TS,Design;DESIGN,Testing;TEST,Accessibility;A11Y',
|
|
68
|
+
'{"wide": true}', null)
|
|
69
|
+
) as i (seq, name, label, type, lov, config, help)
|
|
70
|
+
where a.alias = 'hr' and p.page_no = 50;
|
|
71
|
+
|
|
72
|
+
insert into meta.button (page_id, region_id, seq, name, label, action, hot)
|
|
73
|
+
select p.id, r.id, 10, 'SAVE', 'Save', 'submit', true
|
|
74
|
+
from meta.page p join meta.app a on a.id = p.app_id
|
|
75
|
+
join meta.region r on r.page_id = p.id and r.title = 'Team'
|
|
76
|
+
where a.alias = 'hr' and p.page_no = 50;
|
|
77
|
+
|
|
78
|
+
insert into meta.nav_entry (app_id, parent_id, seq, label, icon, target_page)
|
|
79
|
+
select a.id, n.id, 70, 'Project team', 'users', 50
|
|
80
|
+
from meta.app a join meta.nav_entry n on n.app_id = a.id and n.label = 'Administration' and n.parent_id is null
|
|
81
|
+
where a.alias = 'hr';
|
package/package.json
CHANGED
package/public/app.css
CHANGED
|
@@ -1693,6 +1693,54 @@ td.tc-cell { overflow-wrap: anywhere; }
|
|
|
1693
1693
|
}
|
|
1694
1694
|
.tag-remove:hover, .tag-remove:focus-visible { background: var(--surface-3); }
|
|
1695
1695
|
|
|
1696
|
+
/* (140) shuttle: two lists, the move buttons between them and the order buttons after them (stacked on phones) */
|
|
1697
|
+
.shuttle-ui { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr) auto; gap: 0.5rem; align-items: stretch; }
|
|
1698
|
+
.shuttle-col { display: flex; flex-direction: column; gap: 0.35rem; min-width: 0; }
|
|
1699
|
+
.shuttle-col .shuttle-list { flex: 1; min-height: 9rem; }
|
|
1700
|
+
.shuttle-moves, .shuttle-order { display: flex; flex-direction: column; justify-content: center; gap: 0.3rem; }
|
|
1701
|
+
.shuttle-btn { min-width: 2.4rem; justify-content: center; font-size: 1rem; line-height: 1; }
|
|
1702
|
+
[dir=rtl] .shuttle-moves .shuttle-btn span { display: inline-block; transform: scaleX(-1); }
|
|
1703
|
+
@media (max-width: 640px) {
|
|
1704
|
+
.shuttle-ui { grid-template-columns: minmax(0, 1fr) auto; }
|
|
1705
|
+
.shuttle-col:first-child { grid-column: 1 / -1; }
|
|
1706
|
+
.shuttle-moves { grid-column: 1 / -1; flex-direction: row; justify-content: center; }
|
|
1707
|
+
.shuttle-moves .shuttle-btn span { display: inline-block; transform: rotate(90deg); }
|
|
1708
|
+
}
|
|
1709
|
+
/* (140) select one / select many: a search field with a list box under it; chips above it */
|
|
1710
|
+
.select-pick-ui { position: relative; display: flex; flex-direction: column; gap: 0.3rem; min-width: 0; }
|
|
1711
|
+
.select-pick-list {
|
|
1712
|
+
position: absolute; z-index: 30; top: 100%; inset-inline: 0; margin: 0.15rem 0 0; padding: 0.25rem 0; list-style: none; max-height: 16rem; overflow-y: auto;
|
|
1713
|
+
background: var(--surface); border: 1px solid var(--border); border-radius: calc(var(--radius) * 0.75); box-shadow: var(--shadow);
|
|
1714
|
+
}
|
|
1715
|
+
.select-pick-list[hidden] { display: none; }
|
|
1716
|
+
.select-pick-list li { padding: 0.4rem 0.7rem; cursor: pointer; overflow-wrap: anywhere; }
|
|
1717
|
+
.select-pick-list li[aria-selected=true] { font-weight: 600; }
|
|
1718
|
+
.select-pick-list li[aria-selected=true]::before { content: "✓ "; }
|
|
1719
|
+
.select-pick-list li.is-active, .select-pick-list li:hover { background: var(--surface-3); }
|
|
1720
|
+
.select-pick-list li.select-pick-none { cursor: default; color: var(--muted); }
|
|
1721
|
+
/* (140) a breadcrumb region and a help text region */
|
|
1722
|
+
.region-crumbs .crumbs { font-size: 0.9rem; margin: 0; }
|
|
1723
|
+
.region-crumbs .crumbs [aria-current] { color: var(--text); font-weight: 600; }
|
|
1724
|
+
.help-text { overflow-wrap: anywhere; }
|
|
1725
|
+
.help-text > :first-child { margin-top: 0; }
|
|
1726
|
+
.help-text > :last-child { margin-bottom: 0; }
|
|
1727
|
+
/* (140) classic report templates */
|
|
1728
|
+
.cr-pairs { display: flex; flex-direction: column; gap: 0.75rem; }
|
|
1729
|
+
.cr-pairs dl { display: grid; grid-template-columns: minmax(6rem, max-content) minmax(0, 1fr); gap: 0.25rem 1rem; margin: 0; padding-bottom: 0.75rem; border-bottom: 1px solid var(--border); }
|
|
1730
|
+
.cr-pairs dl:last-child { border-bottom: 0; padding-bottom: 0; }
|
|
1731
|
+
.cr-pairs dt { font-weight: 600; color: var(--muted); overflow-wrap: anywhere; }
|
|
1732
|
+
.cr-pairs dd { margin: 0; overflow-wrap: anywhere; }
|
|
1733
|
+
.cr-badges { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 9rem), 1fr)); gap: 0.6rem; list-style: none; margin: 0; padding: 0; }
|
|
1734
|
+
.cr-badges li { display: flex; flex-direction: column; align-items: center; gap: 0.2rem; padding: 0.7rem; border: 1px solid var(--border); border-radius: var(--radius); text-align: center; overflow-wrap: anywhere; }
|
|
1735
|
+
.cr-badges .cr-badge-value { font-size: 1.4rem; font-weight: 700; }
|
|
1736
|
+
.cr-badges .cr-badge-label { font-size: 0.85rem; color: var(--muted); }
|
|
1737
|
+
.cr-media { list-style: none; margin: 0; padding: 0; }
|
|
1738
|
+
.cr-media li { padding: 0.6rem 0; border-bottom: 1px solid var(--border); overflow-wrap: anywhere; }
|
|
1739
|
+
.cr-media li:last-child { border-bottom: 0; }
|
|
1740
|
+
.cr-media .cr-media-title { font-weight: 600; }
|
|
1741
|
+
.cr-media .cr-media-text { margin: 0.15rem 0 0; color: var(--muted); }
|
|
1742
|
+
@media (max-width: 640px) { .cr-pairs dl { grid-template-columns: minmax(0, 1fr); } }
|
|
1743
|
+
|
|
1696
1744
|
.date-range { display: flex; flex-wrap: wrap; gap: 0.4rem 0.8rem; }
|
|
1697
1745
|
.range-part { display: flex; align-items: center; gap: 0.4rem; flex: 1 1 12rem; min-width: 0; }
|
|
1698
1746
|
.range-part .sub { font-size: 0.85rem; color: var(--muted); min-width: 2.2rem; }
|