@cahyo-dimas/freeday 1.18.0 → 1.20.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/CHANGELOG.md +162 -0
- package/COMPONENTS.md +748 -0
- package/README.id.md +9 -1
- package/README.md +16 -2
- package/USAGE.md +34 -11
- package/adapters/blazor/FdyTable.razor.cs +66 -7
- package/adapters/blazor/TableTypes.cs +6 -0
- package/adapters/react/components/FdyTable.tsx +32 -8
- package/adapters/vue/components/FdyTable.vue +30 -6
- package/dist/freeday.bundle.css +35 -1
- package/dist/freeday.css +30 -0
- package/dist/freeday.tokens.css +5 -1
- package/docs/agent-onboarding.md +151 -0
- package/docs/getting-started.md +454 -0
- package/docs/integrations.md +321 -0
- package/docs/reference-screen.html +461 -0
- package/package.json +9 -3
- package/src/components/list.css +29 -0
- package/tokens/breakpoints.d.ts +3 -0
- package/tokens/breakpoints.mjs +8 -1
- package/src/components/.gitkeep +0 -0
- package/src/freeday-autocomplete.js +0 -135
- package/src/freeday-breakpoint.js +0 -51
- package/src/freeday-carousel.js +0 -111
- package/src/freeday-cascade.js +0 -256
- package/src/freeday-cfl.js +0 -213
- package/src/freeday-chart.js +0 -429
- package/src/freeday-chip.js +0 -83
- package/src/freeday-datepicker.js +0 -321
- package/src/freeday-datetime.js +0 -83
- package/src/freeday-drawer.js +0 -43
- package/src/freeday-form.js +0 -181
- package/src/freeday-mask.js +0 -114
- package/src/freeday-menu.js +0 -93
- package/src/freeday-popover.js +0 -69
- package/src/freeday-rating.js +0 -50
- package/src/freeday-select.js +0 -218
- package/src/freeday-slider.js +0 -34
- package/src/freeday-stepper.js +0 -90
- package/src/freeday-table.js +0 -475
- package/src/freeday-tabs.js +0 -68
- package/src/freeday-timepicker.js +0 -180
- package/src/freeday-toast.js +0 -105
- package/src/freeday-tree.js +0 -94
- package/src/freeday-upload.js +0 -206
|
@@ -0,0 +1,461 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en" data-theme="light" data-density="comfortable">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
+
<title>Freeday — reference screen</title>
|
|
7
|
+
|
|
8
|
+
<!-- The kit in one file: tokens + components (this is what @cahyo-dimas/freeday/css resolves to).
|
|
9
|
+
Note the file name: dist/freeday.css is components ONLY — link that alone and every
|
|
10
|
+
var(--color-*) / var(--space-*) silently falls back, which looks like a broken stylesheet.
|
|
11
|
+
Paths are relative, so this works both in the repo and in node_modules/@cahyo-dimas/freeday/docs/. -->
|
|
12
|
+
<link rel="stylesheet" href="../dist/freeday.bundle.css">
|
|
13
|
+
|
|
14
|
+
<!-- Fonts are NOT shipped by the package. Load them yourself (Fontsource, self-hosted, or a
|
|
15
|
+
<link> to a provider) or override --font-display / --font-body / --font-mono. Without them
|
|
16
|
+
the kit renders in the system fallback, which reads as an unfinished design. -->
|
|
17
|
+
</head>
|
|
18
|
+
<body>
|
|
19
|
+
|
|
20
|
+
<!-- ══════════════════════════════════════════════════════════════════════════════════════════
|
|
21
|
+
REFERENCE SCREEN — one business screen, assembled the intended way.
|
|
22
|
+
|
|
23
|
+
Structure, outermost to innermost:
|
|
24
|
+
.fdy-app the shell (topbar · sidebar · main)
|
|
25
|
+
└ .fdy-page the screen body — vertical section rhythm
|
|
26
|
+
├ .fdy-page__header eyebrow + page title + desc | ONE primary action
|
|
27
|
+
├ .fdy-page-section KPI strip (.fdy-stats — deliberately not cards)
|
|
28
|
+
├ .fdy-page-section chart
|
|
29
|
+
└ .fdy-page-section the data table
|
|
30
|
+
|
|
31
|
+
Every class here exists in COMPONENTS.md. Every value comes from a token — search this file
|
|
32
|
+
for "#" or "px" and you will find none outside the demo-only sizing on the chart wrappers.
|
|
33
|
+
Doctrine behind the choices: USAGE.md.
|
|
34
|
+
══════════════════════════════════════════════════════════════════════════════════════════ -->
|
|
35
|
+
|
|
36
|
+
<div class="fdy-app" id="app">
|
|
37
|
+
<a class="fdy-skip" href="#main">Skip to main content</a>
|
|
38
|
+
|
|
39
|
+
<!-- Sidebar comes FIRST: .fdy-app is a flex row of [sidebar | content]. The brand lives in the
|
|
40
|
+
sidebar (it is sized to match the topbar height), not in the topbar. -->
|
|
41
|
+
<aside class="fdy-app__sidebar" id="sidebar" aria-label="Main navigation">
|
|
42
|
+
<a class="fdy-app__brand" href="#app">
|
|
43
|
+
<span class="fdy-app__brand-mark">
|
|
44
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 7h16M4 12h10M4 17h6"/></svg>
|
|
45
|
+
</span>
|
|
46
|
+
<span class="fdy-app__brand-text">
|
|
47
|
+
<span class="fdy-app__brand-title">Acme Books</span>
|
|
48
|
+
<span class="fdy-app__brand-subtitle">Finance</span>
|
|
49
|
+
</span>
|
|
50
|
+
</a>
|
|
51
|
+
<nav class="fdy-nav">
|
|
52
|
+
<a class="fdy-nav__item" href="#app">
|
|
53
|
+
<span class="fdy-nav__icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="3" width="7" height="7" rx="1.5"/><rect x="14" y="3" width="7" height="7" rx="1.5"/><rect x="3" y="14" width="7" height="7" rx="1.5"/><rect x="14" y="14" width="7" height="7" rx="1.5"/></svg></span>
|
|
54
|
+
<span class="fdy-nav__label">Dashboard</span>
|
|
55
|
+
</a>
|
|
56
|
+
<a class="fdy-nav__item" href="#app" aria-current="page">
|
|
57
|
+
<span class="fdy-nav__icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><path d="M14 2v6h6M9 13h6M9 17h6"/></svg></span>
|
|
58
|
+
<span class="fdy-nav__label">Invoices</span>
|
|
59
|
+
<span class="fdy-nav__badge">12</span>
|
|
60
|
+
</a>
|
|
61
|
+
<a class="fdy-nav__item" href="#app">
|
|
62
|
+
<span class="fdy-nav__icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.87"/></svg></span>
|
|
63
|
+
<span class="fdy-nav__label">Customers</span>
|
|
64
|
+
</a>
|
|
65
|
+
<details class="fdy-nav__group" open>
|
|
66
|
+
<summary class="fdy-nav__grouplabel">Reports</summary>
|
|
67
|
+
<a class="fdy-nav__item" href="#app"><span class="fdy-nav__label">Aging</span></a>
|
|
68
|
+
<a class="fdy-nav__item" href="#app"><span class="fdy-nav__label">Collections</span></a>
|
|
69
|
+
</details>
|
|
70
|
+
</nav>
|
|
71
|
+
</aside>
|
|
72
|
+
|
|
73
|
+
<!-- __content is the column wrapper holding the topbar + main. It exists so the sticky topbar
|
|
74
|
+
has a tall containing block to travel in — a bare flex cell cannot do that. -->
|
|
75
|
+
<div class="fdy-app__content">
|
|
76
|
+
|
|
77
|
+
<header class="fdy-app__topbar">
|
|
78
|
+
<button class="fdy-app__navtoggle" type="button" aria-label="Toggle navigation" aria-expanded="true" aria-controls="sidebar">
|
|
79
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M3 6h18M3 12h18M3 18h18"/></svg>
|
|
80
|
+
</button>
|
|
81
|
+
|
|
82
|
+
<!-- .fdy-app__title carries an auto-spacer (margin-right:auto): everything after it sits at
|
|
83
|
+
the right edge. -->
|
|
84
|
+
<h1 class="fdy-app__title fdy-hide-below-md">Receivables</h1>
|
|
85
|
+
|
|
86
|
+
<div class="fdy-input-group fdy-hide-below-md" style="max-width:14rem">
|
|
87
|
+
<span class="fdy-input-group__addon fdy-input-group__addon--icon">
|
|
88
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="11" cy="11" r="7"/><path d="m21 21-4.35-4.35"/></svg>
|
|
89
|
+
</span>
|
|
90
|
+
<input class="fdy-input" type="search" placeholder="Search…" aria-label="Search the app">
|
|
91
|
+
</div>
|
|
92
|
+
|
|
93
|
+
<span class="fdy-badge-wrap">
|
|
94
|
+
<button class="fdy-btn fdy-btn--ghost fdy-btn--icon" type="button" aria-label="Notifications — 3 new">
|
|
95
|
+
<span class="fdy-btn__icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M18 8a6 6 0 0 0-12 0c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.7 21a2 2 0 0 1-3.4 0"/></svg></span>
|
|
96
|
+
</button>
|
|
97
|
+
<span class="fdy-badge-ov fdy-badge-ov--danger" aria-hidden="true">3</span>
|
|
98
|
+
</span>
|
|
99
|
+
|
|
100
|
+
<div class="fdy-menu-wrap" data-fdy-menu>
|
|
101
|
+
<button class="fdy-btn fdy-btn--ghost" type="button" aria-haspopup="menu" aria-expanded="false" aria-label="User menu">
|
|
102
|
+
<span class="fdy-avatar fdy-avatar--sm fdy-avatar--tone-3">AK</span>
|
|
103
|
+
</button>
|
|
104
|
+
<ul class="fdy-menu fdy-menu--end" role="menu" hidden>
|
|
105
|
+
<li role="none"><button class="fdy-menu__item" role="menuitem" type="button">Profile</button></li>
|
|
106
|
+
<li role="none"><button class="fdy-menu__item" role="menuitem" type="button" id="toggle-theme">Toggle theme</button></li>
|
|
107
|
+
<li role="none"><button class="fdy-menu__item" role="menuitem" type="button" id="toggle-density">Toggle density</button></li>
|
|
108
|
+
<li role="none"><hr class="fdy-menu__sep"></li>
|
|
109
|
+
<li role="none"><button class="fdy-menu__item fdy-menu__item--danger" role="menuitem" type="button">Sign out</button></li>
|
|
110
|
+
</ul>
|
|
111
|
+
</div>
|
|
112
|
+
</header>
|
|
113
|
+
|
|
114
|
+
<!-- __main is the padded content area (--space-8). The screen goes straight inside it. -->
|
|
115
|
+
<main class="fdy-app__main" id="main" tabindex="-1">
|
|
116
|
+
|
|
117
|
+
<!-- ═══ THE SCREEN ═══ -->
|
|
118
|
+
<div class="fdy-page">
|
|
119
|
+
|
|
120
|
+
<!-- One page header. One primary action — everything else is ghost. -->
|
|
121
|
+
<header class="fdy-page__header">
|
|
122
|
+
<div class="fdy-page__heading">
|
|
123
|
+
<p class="fdy-eyebrow">Sales</p>
|
|
124
|
+
<h2 class="fdy-title-page">Receivables</h2>
|
|
125
|
+
<p class="fdy-page__desc">Every open invoice, with the amount still outstanding per customer.</p>
|
|
126
|
+
</div>
|
|
127
|
+
<div class="fdy-page__actions">
|
|
128
|
+
<button class="fdy-btn fdy-btn--ghost" type="button" id="btn-export">Export</button>
|
|
129
|
+
<button class="fdy-btn" type="button" id="btn-new">New invoice</button>
|
|
130
|
+
</div>
|
|
131
|
+
</header>
|
|
132
|
+
|
|
133
|
+
<!-- KPI strip: .fdy-stat tiles, NOT cards — a metric row must not read as a card grid. -->
|
|
134
|
+
<section class="fdy-page-section" aria-labelledby="kpi-h">
|
|
135
|
+
<h3 class="fdy-title-section fdy-visually-hidden" id="kpi-h">Key figures</h3>
|
|
136
|
+
<div class="fdy-stats fdy-stats--boxed">
|
|
137
|
+
<div class="fdy-stat">
|
|
138
|
+
<span class="fdy-stat__label">Outstanding</span>
|
|
139
|
+
<span class="fdy-stat__value">8.42<small> M</small></span>
|
|
140
|
+
<span class="fdy-stat__meta">across 34 invoices</span>
|
|
141
|
+
</div>
|
|
142
|
+
<div class="fdy-stat">
|
|
143
|
+
<span class="fdy-stat__label">Overdue</span>
|
|
144
|
+
<span class="fdy-stat__value">1.19<small> M</small></span>
|
|
145
|
+
<span class="fdy-stat__meta"><span class="fdy-badge fdy-badge--warning">7 invoices</span></span>
|
|
146
|
+
</div>
|
|
147
|
+
<div class="fdy-stat">
|
|
148
|
+
<span class="fdy-stat__label">Collected (MTD)</span>
|
|
149
|
+
<span class="fdy-stat__value">5.60<small> M</small></span>
|
|
150
|
+
<span class="fdy-stat__meta">target 6.00 M</span>
|
|
151
|
+
</div>
|
|
152
|
+
<div class="fdy-stat">
|
|
153
|
+
<span class="fdy-stat__label">Avg. days to pay</span>
|
|
154
|
+
<span class="fdy-stat__value">27</span>
|
|
155
|
+
<span class="fdy-stat__meta">terms: 30 days</span>
|
|
156
|
+
</div>
|
|
157
|
+
</div>
|
|
158
|
+
</section>
|
|
159
|
+
|
|
160
|
+
<!-- A section with a chart. Flat section, one card holding the chart. -->
|
|
161
|
+
<section class="fdy-page-section" aria-labelledby="trend-h">
|
|
162
|
+
<div class="fdy-page-section__head">
|
|
163
|
+
<h3 class="fdy-title-section" id="trend-h">Collection trend</h3>
|
|
164
|
+
<p class="fdy-text-caption">Last six months</p>
|
|
165
|
+
</div>
|
|
166
|
+
<div class="fdy-card">
|
|
167
|
+
<div class="fdy-card__body">
|
|
168
|
+
<div data-fdy-chart="line"
|
|
169
|
+
data-labels="Feb,Mar,Apr,May,Jun,Jul"
|
|
170
|
+
data-series='[{"label":"Invoiced","values":[62,68,75,71,83,88]},{"label":"Collected","values":[54,60,66,69,74,81]}]'
|
|
171
|
+
data-fdy-format="number"
|
|
172
|
+
role="img"
|
|
173
|
+
aria-label="Invoiced versus collected, in millions: invoiced rose from 62 to 88, collected from 54 to 81">
|
|
174
|
+
<table>
|
|
175
|
+
<caption>Invoiced vs collected (millions)</caption>
|
|
176
|
+
<tr><th scope="col">Month</th><th scope="col">Invoiced</th><th scope="col">Collected</th></tr>
|
|
177
|
+
<tr><td>Jul</td><td>88</td><td>81</td></tr>
|
|
178
|
+
</table>
|
|
179
|
+
</div>
|
|
180
|
+
</div>
|
|
181
|
+
</div>
|
|
182
|
+
</section>
|
|
183
|
+
|
|
184
|
+
<!-- The data table, with its filter bar composed onto the toolbar baseline.
|
|
185
|
+
KNOWN GAP: the vanilla freeday-table.js writes its footer/bulk strings in Indonesian
|
|
186
|
+
("Menampilkan 1–5 dari 7", "N dipilih") and offers no override, so they stay Indonesian
|
|
187
|
+
on this English page. The Vue/React/Blazor <FdyTable> components default to English.
|
|
188
|
+
If you need English in a static page, render those two nodes yourself from the
|
|
189
|
+
fdy-table-change event instead of using data-fdy-table-info / -bulk-count. -->
|
|
190
|
+
<section class="fdy-page-section" aria-labelledby="list-h">
|
|
191
|
+
<div class="fdy-page-section__head">
|
|
192
|
+
<h3 class="fdy-title-section" id="list-h">Open invoices</h3>
|
|
193
|
+
</div>
|
|
194
|
+
|
|
195
|
+
<!-- md and up: the table. Below md it is hidden and the flat list below takes over. -->
|
|
196
|
+
<div class="fdy-datatable fdy-hide-below-md" data-fdy-table data-page-size="5">
|
|
197
|
+
<div class="fdy-table-toolbar fdy-filterbar">
|
|
198
|
+
<div class="fdy-field fdy-field--w-grow">
|
|
199
|
+
<span class="fdy-label" id="f-q">Search</span>
|
|
200
|
+
<div class="fdy-input-group">
|
|
201
|
+
<span class="fdy-input-group__addon fdy-input-group__addon--icon">
|
|
202
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="11" cy="11" r="7"/><path d="m21 21-4.35-4.35"/></svg>
|
|
203
|
+
</span>
|
|
204
|
+
<input class="fdy-input" type="search" placeholder="Invoice or customer…" data-fdy-table-search aria-labelledby="f-q">
|
|
205
|
+
</div>
|
|
206
|
+
</div>
|
|
207
|
+
<div class="fdy-field fdy-field--w-sm">
|
|
208
|
+
<span class="fdy-label" id="f-st">Status</span>
|
|
209
|
+
<div class="fdy-combo" data-fdy-combo data-value="all">
|
|
210
|
+
<button type="button" class="fdy-combo__button" role="combobox" aria-haspopup="listbox" aria-expanded="false" aria-labelledby="f-st f-st-v">
|
|
211
|
+
<span class="fdy-combo__value" id="f-st-v">All</span>
|
|
212
|
+
</button>
|
|
213
|
+
<ul class="fdy-combo__listbox" role="listbox" aria-labelledby="f-st" hidden>
|
|
214
|
+
<li class="fdy-combo__option" role="option" data-value="all" aria-selected="true"><span class="fdy-combo__check">✓</span>All</li>
|
|
215
|
+
<li class="fdy-combo__option" role="option" data-value="open" aria-selected="false"><span class="fdy-combo__check"></span>Open</li>
|
|
216
|
+
<li class="fdy-combo__option" role="option" data-value="overdue" aria-selected="false"><span class="fdy-combo__check"></span>Overdue</li>
|
|
217
|
+
</ul>
|
|
218
|
+
</div>
|
|
219
|
+
</div>
|
|
220
|
+
<div class="fdy-field fdy-field--w-2xl">
|
|
221
|
+
<span class="fdy-label">Issued between</span>
|
|
222
|
+
<div class="fdy-daterange" data-fdy-daterange role="group" aria-label="Issued between">
|
|
223
|
+
<div data-fdy-datepicker data-role="from" data-placeholder="From" data-label="Issued from"></div>
|
|
224
|
+
<span class="fdy-daterange__sep" aria-hidden="true">–</span>
|
|
225
|
+
<div data-fdy-datepicker data-role="to" data-placeholder="To" data-label="Issued to"></div>
|
|
226
|
+
</div>
|
|
227
|
+
</div>
|
|
228
|
+
<div class="fdy-filterbar__actions">
|
|
229
|
+
<button class="fdy-btn fdy-btn--ghost" type="button">Reset</button>
|
|
230
|
+
</div>
|
|
231
|
+
</div>
|
|
232
|
+
|
|
233
|
+
<div class="fdy-table-bulkbar" data-fdy-table-bulk hidden role="region" aria-label="Bulk actions">
|
|
234
|
+
<span class="fdy-table-bulkbar__count" data-fdy-table-bulk-count aria-live="polite">0 selected</span>
|
|
235
|
+
<span class="fdy-table-bulkbar__spacer"></span>
|
|
236
|
+
<div class="fdy-table-bulkbar__actions">
|
|
237
|
+
<button class="fdy-btn fdy-btn--ghost fdy-btn--sm" type="button">Send reminder</button>
|
|
238
|
+
<button class="fdy-btn fdy-btn--ghost fdy-btn--sm" type="button" data-fdy-table-bulk-clear>Clear</button>
|
|
239
|
+
</div>
|
|
240
|
+
</div>
|
|
241
|
+
|
|
242
|
+
<div class="fdy-table-scroll">
|
|
243
|
+
<table class="fdy-table">
|
|
244
|
+
<caption class="fdy-visually-hidden">Open invoices, sortable and filterable</caption>
|
|
245
|
+
<thead>
|
|
246
|
+
<tr>
|
|
247
|
+
<th class="fdy-table__selcol" scope="col"><input type="checkbox" class="fdy-checkbox" data-fdy-select-all aria-label="Select all rows"></th>
|
|
248
|
+
<th scope="col"><button type="button" class="fdy-table__sortbtn" data-fdy-sort>Invoice</button></th>
|
|
249
|
+
<th scope="col" data-fdy-filter="text"><button type="button" class="fdy-table__sortbtn" data-fdy-sort>Customer</button></th>
|
|
250
|
+
<th scope="col" data-fdy-filter="enum"><button type="button" class="fdy-table__sortbtn" data-fdy-sort>Status</button></th>
|
|
251
|
+
<th scope="col">Due</th>
|
|
252
|
+
<th scope="col" class="fdy-table__num" data-fdy-filter="number"><button type="button" class="fdy-table__sortbtn" data-fdy-sort="number">Amount</button></th>
|
|
253
|
+
</tr>
|
|
254
|
+
</thead>
|
|
255
|
+
<tbody>
|
|
256
|
+
<tr>
|
|
257
|
+
<td class="fdy-table__selcol"><input type="checkbox" class="fdy-checkbox" data-fdy-row-select aria-label="Select INV-2041"></td>
|
|
258
|
+
<td class="fdy-mono">INV-2041</td><td>Acme Ltd</td>
|
|
259
|
+
<td><span class="fdy-badge fdy-badge--success">Paid</span></td>
|
|
260
|
+
<td>30 Jul 2026</td><td class="fdy-table__num" data-sort-value="1240000">1,240,000</td>
|
|
261
|
+
</tr>
|
|
262
|
+
<tr>
|
|
263
|
+
<td class="fdy-table__selcol"><input type="checkbox" class="fdy-checkbox" data-fdy-row-select aria-label="Select INV-2042"></td>
|
|
264
|
+
<td class="fdy-mono">INV-2042</td><td>Northwind Trading</td>
|
|
265
|
+
<td><span class="fdy-badge fdy-badge--warning">Overdue</span></td>
|
|
266
|
+
<td>12 Jul 2026</td><td class="fdy-table__num" data-sort-value="290000">290,000</td>
|
|
267
|
+
</tr>
|
|
268
|
+
<tr>
|
|
269
|
+
<td class="fdy-table__selcol"><input type="checkbox" class="fdy-checkbox" data-fdy-row-select aria-label="Select INV-2043"></td>
|
|
270
|
+
<td class="fdy-mono">INV-2043</td><td>Globex Supply</td>
|
|
271
|
+
<td><span class="fdy-badge fdy-badge--info">Draft</span></td>
|
|
272
|
+
<td>—</td><td class="fdy-table__num" data-sort-value="0">0</td>
|
|
273
|
+
</tr>
|
|
274
|
+
<tr>
|
|
275
|
+
<td class="fdy-table__selcol"><input type="checkbox" class="fdy-checkbox" data-fdy-row-select aria-label="Select INV-2044"></td>
|
|
276
|
+
<td class="fdy-mono">INV-2044</td><td>Initech Partners</td>
|
|
277
|
+
<td><span class="fdy-badge fdy-badge--success">Paid</span></td>
|
|
278
|
+
<td>02 Aug 2026</td><td class="fdy-table__num" data-sort-value="4750000">4,750,000</td>
|
|
279
|
+
</tr>
|
|
280
|
+
<tr>
|
|
281
|
+
<td class="fdy-table__selcol"><input type="checkbox" class="fdy-checkbox" data-fdy-row-select aria-label="Select INV-2045"></td>
|
|
282
|
+
<td class="fdy-mono">INV-2045</td><td>Umbra Logistics</td>
|
|
283
|
+
<td><span class="fdy-badge fdy-badge--warning">Overdue</span></td>
|
|
284
|
+
<td>08 Jul 2026</td><td class="fdy-table__num" data-sort-value="820000">820,000</td>
|
|
285
|
+
</tr>
|
|
286
|
+
<tr>
|
|
287
|
+
<td class="fdy-table__selcol"><input type="checkbox" class="fdy-checkbox" data-fdy-row-select aria-label="Select INV-2046"></td>
|
|
288
|
+
<td class="fdy-mono">INV-2046</td><td>Stark Materials</td>
|
|
289
|
+
<td><span class="fdy-badge fdy-badge--danger">Cancelled</span></td>
|
|
290
|
+
<td>—</td><td class="fdy-table__num" data-sort-value="150000">150,000</td>
|
|
291
|
+
</tr>
|
|
292
|
+
<tr>
|
|
293
|
+
<td class="fdy-table__selcol"><input type="checkbox" class="fdy-checkbox" data-fdy-row-select aria-label="Select INV-2047"></td>
|
|
294
|
+
<td class="fdy-mono">INV-2047</td><td>Acme Ltd</td>
|
|
295
|
+
<td><span class="fdy-badge fdy-badge--success">Paid</span></td>
|
|
296
|
+
<td>21 Aug 2026</td><td class="fdy-table__num" data-sort-value="3120000">3,120,000</td>
|
|
297
|
+
</tr>
|
|
298
|
+
</tbody>
|
|
299
|
+
</table>
|
|
300
|
+
</div>
|
|
301
|
+
|
|
302
|
+
<div class="fdy-table-footer">
|
|
303
|
+
<span class="fdy-table-footer__info" data-fdy-table-info></span>
|
|
304
|
+
<nav class="fdy-pagination" aria-label="Table pages" data-fdy-table-pagination></nav>
|
|
305
|
+
</div>
|
|
306
|
+
</div>
|
|
307
|
+
|
|
308
|
+
<!-- Below md: the SAME rows as a flat list. .fdy-list is the flat container the doctrine
|
|
309
|
+
asks for — a stack of .fdy-card would put a 34px lift under every row.
|
|
310
|
+
In a framework app you would not duplicate the markup: hide <FdyTable> below md, feed
|
|
311
|
+
this list from its `process` event, and drive both from a controlled `pageIndex` with
|
|
312
|
+
ONE pager rendered outside the table. See COMPONENTS.md §Data table. -->
|
|
313
|
+
<ul class="fdy-list fdy-hide-above-md">
|
|
314
|
+
<li>
|
|
315
|
+
<button type="button" class="fdy-list__row fdy-list__row--button">
|
|
316
|
+
<span class="fdy-list__main">
|
|
317
|
+
<span class="fdy-list__title">Acme Ltd</span>
|
|
318
|
+
<span class="fdy-list__meta"><span class="fdy-mono">INV-2041</span> · due 30 Jul <span class="fdy-badge fdy-badge--success">Paid</span></span>
|
|
319
|
+
</span>
|
|
320
|
+
<span class="fdy-list__aside fdy-mono">1,240,000</span>
|
|
321
|
+
</button>
|
|
322
|
+
</li>
|
|
323
|
+
<li>
|
|
324
|
+
<button type="button" class="fdy-list__row fdy-list__row--button">
|
|
325
|
+
<span class="fdy-list__main">
|
|
326
|
+
<span class="fdy-list__title">Northwind Trading</span>
|
|
327
|
+
<span class="fdy-list__meta"><span class="fdy-mono">INV-2042</span> · due 12 Jul <span class="fdy-badge fdy-badge--warning">Overdue</span></span>
|
|
328
|
+
</span>
|
|
329
|
+
<span class="fdy-list__aside fdy-mono">290,000</span>
|
|
330
|
+
</button>
|
|
331
|
+
</li>
|
|
332
|
+
<li>
|
|
333
|
+
<button type="button" class="fdy-list__row fdy-list__row--button">
|
|
334
|
+
<span class="fdy-list__main">
|
|
335
|
+
<span class="fdy-list__title">Globex Supply</span>
|
|
336
|
+
<span class="fdy-list__meta"><span class="fdy-mono">INV-2043</span> · draft <span class="fdy-badge fdy-badge--info">Draft</span></span>
|
|
337
|
+
</span>
|
|
338
|
+
<span class="fdy-list__aside fdy-mono">0</span>
|
|
339
|
+
</button>
|
|
340
|
+
</li>
|
|
341
|
+
</ul>
|
|
342
|
+
</section>
|
|
343
|
+
|
|
344
|
+
<!-- A detail region: key-value pairs + a timeline. Flat section, one card each. -->
|
|
345
|
+
<section class="fdy-page-section" aria-labelledby="detail-h">
|
|
346
|
+
<div class="fdy-page-section__head">
|
|
347
|
+
<h3 class="fdy-title-section" id="detail-h">INV-2042 — detail</h3>
|
|
348
|
+
<button class="fdy-btn fdy-btn--text" type="button">Open full record</button>
|
|
349
|
+
</div>
|
|
350
|
+
<div class="fdy-card">
|
|
351
|
+
<div class="fdy-card__body">
|
|
352
|
+
<h4 class="fdy-title-card">Northwind Trading</h4>
|
|
353
|
+
<dl class="fdy-dl">
|
|
354
|
+
<dt>Invoice</dt><dd class="fdy-mono">INV-2042</dd>
|
|
355
|
+
<dt>Status</dt><dd><span class="fdy-badge fdy-badge--warning">Overdue</span></dd>
|
|
356
|
+
<dt>Issued</dt><dd>12 Jun 2026</dd>
|
|
357
|
+
<dt>Due</dt><dd>12 Jul 2026</dd>
|
|
358
|
+
<dt>Amount</dt><dd>290,000</dd>
|
|
359
|
+
</dl>
|
|
360
|
+
</div>
|
|
361
|
+
</div>
|
|
362
|
+
</section>
|
|
363
|
+
|
|
364
|
+
</div>
|
|
365
|
+
<!-- ═══ /THE SCREEN ═══ -->
|
|
366
|
+
|
|
367
|
+
</main>
|
|
368
|
+
|
|
369
|
+
</div><!-- /.fdy-app__content -->
|
|
370
|
+
|
|
371
|
+
<div class="fdy-app__backdrop"></div>
|
|
372
|
+
</div>
|
|
373
|
+
|
|
374
|
+
<!-- Native <dialog>: focus trap, Esc and backdrop are the browser's job, not yours. -->
|
|
375
|
+
<dialog class="fdy-modal" id="new-invoice" aria-labelledby="new-invoice-t">
|
|
376
|
+
<form method="dialog" data-fdy-validate>
|
|
377
|
+
<div class="fdy-modal__header">
|
|
378
|
+
<h2 class="fdy-modal__title" id="new-invoice-t">New invoice</h2>
|
|
379
|
+
<button class="fdy-modal__close" type="button" aria-label="Close" data-close>×</button>
|
|
380
|
+
</div>
|
|
381
|
+
<div class="fdy-modal__body">
|
|
382
|
+
<div class="fdy-form-grid">
|
|
383
|
+
<label class="fdy-field">
|
|
384
|
+
<span class="fdy-label">Customer</span>
|
|
385
|
+
<input class="fdy-input" name="customer" required data-fdy-msg-required="Customer is required.">
|
|
386
|
+
</label>
|
|
387
|
+
<label class="fdy-field">
|
|
388
|
+
<span class="fdy-label">Invoice no.</span>
|
|
389
|
+
<input class="fdy-input fdy-mono" name="no" value="INV-2048" readonly>
|
|
390
|
+
</label>
|
|
391
|
+
<div class="fdy-field">
|
|
392
|
+
<span class="fdy-label">Issue date</span>
|
|
393
|
+
<div data-fdy-datepicker data-value="2026-08-12" data-label="Issue date"></div>
|
|
394
|
+
</div>
|
|
395
|
+
<label class="fdy-field">
|
|
396
|
+
<span class="fdy-label">Amount</span>
|
|
397
|
+
<div class="fdy-input-group">
|
|
398
|
+
<span class="fdy-input-group__addon">Rp</span>
|
|
399
|
+
<input class="fdy-input" name="amount" inputmode="numeric" required data-fdy-msg-required="Amount is required.">
|
|
400
|
+
</div>
|
|
401
|
+
</label>
|
|
402
|
+
<label class="fdy-field fdy-field--full fdy-switch">
|
|
403
|
+
<input type="checkbox" checked> Email the invoice to the customer
|
|
404
|
+
</label>
|
|
405
|
+
</div>
|
|
406
|
+
</div>
|
|
407
|
+
<div class="fdy-modal__footer">
|
|
408
|
+
<button class="fdy-btn fdy-btn--ghost" type="button" data-close>Cancel</button>
|
|
409
|
+
<button class="fdy-btn" type="submit">Save invoice</button>
|
|
410
|
+
</div>
|
|
411
|
+
</form>
|
|
412
|
+
</dialog>
|
|
413
|
+
|
|
414
|
+
<!-- Enhancers: only the ones this screen actually uses. Zero dependencies, load order free. -->
|
|
415
|
+
<script src="../dist/freeday-popover.js"></script>
|
|
416
|
+
<script src="../dist/freeday-select.js"></script>
|
|
417
|
+
<script src="../dist/freeday-datepicker.js"></script>
|
|
418
|
+
<script src="../dist/freeday-menu.js"></script>
|
|
419
|
+
<script src="../dist/freeday-table.js"></script>
|
|
420
|
+
<script src="../dist/freeday-chart.js"></script>
|
|
421
|
+
<script src="../dist/freeday-form.js"></script>
|
|
422
|
+
<script src="../dist/freeday-toast.js"></script>
|
|
423
|
+
|
|
424
|
+
<script>
|
|
425
|
+
// The shell's only wiring: the nav toggle. Two state classes, no library.
|
|
426
|
+
// Above 720px the sidebar collapses to zero width (--nav-collapsed); at or below it slides in as
|
|
427
|
+
// an off-canvas drawer (--nav-open). 720px is where app-shell.css switches — keep them in step.
|
|
428
|
+
const app = document.getElementById('app');
|
|
429
|
+
const toggle = app.querySelector('.fdy-app__navtoggle');
|
|
430
|
+
const wide = () => window.matchMedia('(min-width: 721px)').matches;
|
|
431
|
+
toggle.addEventListener('click', () => {
|
|
432
|
+
const cls = wide() ? 'fdy-app--nav-collapsed' : 'fdy-app--nav-open';
|
|
433
|
+
const open = app.classList.toggle(cls);
|
|
434
|
+
toggle.setAttribute('aria-expanded', String(wide() ? !open : open));
|
|
435
|
+
});
|
|
436
|
+
app.querySelector('.fdy-app__backdrop').addEventListener('click', () => {
|
|
437
|
+
app.classList.remove('fdy-app--nav-open');
|
|
438
|
+
toggle.setAttribute('aria-expanded', 'false');
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
// Theme + density live on <html>, set once — never per component.
|
|
442
|
+
const root = document.documentElement;
|
|
443
|
+
document.getElementById('toggle-theme').addEventListener('click', () => {
|
|
444
|
+
root.dataset.theme = root.dataset.theme === 'dark' ? 'light' : 'dark';
|
|
445
|
+
});
|
|
446
|
+
document.getElementById('toggle-density').addEventListener('click', () => {
|
|
447
|
+
root.dataset.density = root.dataset.density === 'compact' ? 'comfortable' : 'compact';
|
|
448
|
+
});
|
|
449
|
+
|
|
450
|
+
document.getElementById('btn-new').addEventListener('click', () => {
|
|
451
|
+
document.getElementById('new-invoice').showModal();
|
|
452
|
+
});
|
|
453
|
+
document.querySelectorAll('#new-invoice [data-close]').forEach(b => {
|
|
454
|
+
b.addEventListener('click', () => document.getElementById('new-invoice').close());
|
|
455
|
+
});
|
|
456
|
+
document.getElementById('btn-export').addEventListener('click', () => {
|
|
457
|
+
Freeday.toast({ variant: 'info', title: 'Export queued', message: 'The file will download shortly.', key: 'export' });
|
|
458
|
+
});
|
|
459
|
+
</script>
|
|
460
|
+
</body>
|
|
461
|
+
</html>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cahyo-dimas/freeday",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.20.0",
|
|
4
4
|
"description": "Freeday — token-driven, framework-agnostic UI KIT (design source-of-truth).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -21,7 +21,8 @@
|
|
|
21
21
|
},
|
|
22
22
|
"files": [
|
|
23
23
|
"dist",
|
|
24
|
-
"src",
|
|
24
|
+
"src/base.css",
|
|
25
|
+
"src/components",
|
|
25
26
|
"adapters",
|
|
26
27
|
"tokens/tokens.json",
|
|
27
28
|
"tokens/breakpoints.mjs",
|
|
@@ -29,7 +30,12 @@
|
|
|
29
30
|
"README.md",
|
|
30
31
|
"README.id.md",
|
|
31
32
|
"USAGE.md",
|
|
32
|
-
"
|
|
33
|
+
"COMPONENTS.md",
|
|
34
|
+
"CHANGELOG.md",
|
|
35
|
+
"docs/getting-started.md",
|
|
36
|
+
"docs/integrations.md",
|
|
37
|
+
"docs/agent-onboarding.md",
|
|
38
|
+
"docs/reference-screen.html"
|
|
33
39
|
],
|
|
34
40
|
"exports": {
|
|
35
41
|
".": { "types": "./dist/freeday.d.ts", "default": "./dist/freeday.js" },
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/* Freeday — List: the FLAT row container.
|
|
2
|
+
*
|
|
3
|
+
* USAGE.md §3 puts list rows among the surfaces that should be flat, but until now the only
|
|
4
|
+
* container the kit shipped was .fdy-card — which carries --shadow-lift (a real 34px lift). A
|
|
5
|
+
* responsive table that becomes a list below `md` therefore had to choose between a stack of
|
|
6
|
+
* shadowed cards (against the doctrine) or a hand-built box, which needs a colour and so escapes
|
|
7
|
+
* the token system. This is that missing container: one flat surface, hairline dividers, no shadow.
|
|
8
|
+
*
|
|
9
|
+
* Not to be confused with .fdy-list-reset (base.css), which only strips UA bullets/indent.
|
|
10
|
+
* Works on <ul>/<ol> (list-style is reset here) or on plain <div>s. */
|
|
11
|
+
.fdy-list{list-style:none;margin:0;padding:0;background:var(--color-surface);border:var(--bw) solid var(--color-border);border-radius:var(--radius-lg);overflow:hidden;}
|
|
12
|
+
.fdy-list__row{display:flex;align-items:center;gap:var(--space-3);padding:var(--space-4) var(--space-5);min-width:0;}
|
|
13
|
+
/* Divider between rows. Two shapes are supported and both are load-bearing: rows as direct children
|
|
14
|
+
* of the list, and rows wrapped in <li> (the semantic shape, where the ADJACENT siblings are the
|
|
15
|
+
* <li>s — a bare `.fdy-list__row + .fdy-list__row` silently matches nothing there). */
|
|
16
|
+
.fdy-list__row + .fdy-list__row,
|
|
17
|
+
.fdy-list > * + * > .fdy-list__row{border-top:var(--bw) solid var(--color-border-muted);}
|
|
18
|
+
/* A row that is itself the control: render it as <button>/<a> and the UA box is reset without
|
|
19
|
+
* touching the list surface (same contract as .fdy-card--button). */
|
|
20
|
+
.fdy-list__row--button{width:100%;text-align:inherit;color:inherit;font:inherit;background:none;border:0;appearance:none;-webkit-appearance:none;cursor:pointer;}
|
|
21
|
+
.fdy-list__row--button:hover,.fdy-list__row--interactive:hover{background:var(--color-surface-2);}
|
|
22
|
+
.fdy-list__row--button:focus-visible{outline:none;box-shadow:inset 0 0 0 2px var(--color-primary);}
|
|
23
|
+
.fdy-list__row--interactive{cursor:pointer;}
|
|
24
|
+
/* Row internals: a title/meta stack that truncates, and a trailing slot pinned right. */
|
|
25
|
+
.fdy-list__main{display:flex;flex-direction:column;gap:var(--space-1);min-width:0;flex:1;}
|
|
26
|
+
.fdy-list__title{font-weight:var(--weight-medium);color:var(--color-text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
|
|
27
|
+
.fdy-list__meta{font-size:var(--text-sm);color:var(--color-text-muted);display:flex;align-items:center;gap:var(--space-2);flex-wrap:wrap;}
|
|
28
|
+
.fdy-list__aside{flex:none;display:flex;align-items:center;gap:var(--space-2);}
|
|
29
|
+
/* Density: rows tighten with the rest of the kit (--space-* mid-range steps under compact). */
|
package/tokens/breakpoints.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
// Types for tokens/breakpoints.mjs — the JS-side breakpoint scale in px
|
|
2
2
|
// (mirrors the sm/md/lg/xl utilities in src/components/breakpoints.css).
|
|
3
3
|
export declare const breakpoints: {
|
|
4
|
+
/** Width at which .fdy-app's sidebar turns from off-canvas drawer into a static column.
|
|
5
|
+
* Not part of the sm/md/lg/xl ramp — it mirrors app-shell.css and nothing else. */
|
|
6
|
+
nav: number;
|
|
4
7
|
sm: number;
|
|
5
8
|
md: number;
|
|
6
9
|
lg: number;
|
package/tokens/breakpoints.mjs
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
// Freeday breakpoint scale in px — mirrors src/components/breakpoints.css utilities
|
|
2
2
|
// (sm/md/lg/xl). CSS @media can't read custom properties, so this is the JS-side
|
|
3
3
|
// source of the scale for matchMedia / app @media alignment.
|
|
4
|
-
|
|
4
|
+
//
|
|
5
|
+
// `nav` is not part of the sm/md/lg/xl ramp: it is the width at which .fdy-app switches the
|
|
6
|
+
// sidebar from an off-canvas drawer (below) to a static column (at and above), hard-wired in
|
|
7
|
+
// src/components/app-shell.css. Anything that has to agree with the shell — a matchMedia guard
|
|
8
|
+
// deciding whether the nav toggle sets --nav-open or --nav-collapsed, a utility-framework
|
|
9
|
+
// variant — must use THIS number, not md. Aligning such code to md (960) leaves 721–959px
|
|
10
|
+
// broken: the sidebar is already static while the script still thinks it is an overlay.
|
|
11
|
+
export const breakpoints = { nav: 721, sm: 600, md: 960, lg: 1280, xl: 1920 };
|
package/src/components/.gitkeep
DELETED
|
File without changes
|