@hawiyah/angular 0.0.0-stage → 0.2.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.
package/dist/README.md ADDED
@@ -0,0 +1,335 @@
1
+ # @hawiyah/angular
2
+
3
+ Angular components for Hawiyah — هوية, a UI library built to comply with the DGA
4
+ Platforms Code. Install with `npm install @hawiyah/styles @hawiyah/angular`. This is a
5
+ pre-1.0 release, so a minor version may still change its API.
6
+
7
+ The 77 catalog entries render native HTML with Angular templates. There are no
8
+ custom-element wrappers, schemas, runtime HTML injection, or framework renderers
9
+ inside core. Angular owns state and DOM; the shared core supplies pure combobox
10
+ transitions and keyboard navigation. Shared `hw-` classes provide appearance.
11
+
12
+ ## Use
13
+
14
+ Build the workspace packages before starting the example. Import the standalone
15
+ components you use. The library builds with `ng-packagr` to Angular Package Format
16
+ (partial compilation); production Angular applications link it through their
17
+ normal Angular AOT build.
18
+
19
+ ```ts
20
+ import { Component } from '@angular/core';
21
+ import { FormsModule } from '@angular/forms';
22
+ import { HwTextFieldComponent, HwComboboxComponent, HwButtonDirective } from '@hawiyah/angular';
23
+
24
+ @Component({
25
+ standalone: true,
26
+ imports: [FormsModule, HwTextFieldComponent, HwComboboxComponent, HwButtonDirective],
27
+ template: `
28
+ <form #form="ngForm" (ngSubmit)="save()">
29
+ <hw-text-field controlId="name" label="Name" name="name" [(ngModel)]="name" [required]="true" />
30
+ <hw-combobox controlId="city" label="City" name="city" [(ngModel)]="city" [options]="cities" />
31
+ <button hwButton type="submit">Save</button>
32
+ <button hwButton variant="secondary" type="button" (click)="form.resetForm()">Reset</button>
33
+ </form>
34
+ `,
35
+ })
36
+ export class Example {
37
+ name = ''; city = '';
38
+ cities = [{value: 'riyadh', label: 'الرياض · Riyadh'}];
39
+ save() { /* application action */ }
40
+ }
41
+ ```
42
+
43
+ Load `@hawiyah/styles/styles.css` once in the host application. The optional
44
+ `@hawiyah/styles/reset.css` is separate. Themes apply to a containing element:
45
+
46
+ ```html
47
+ <main data-hw-theme="dga" data-hw-mode="light"
48
+ data-hw-density="comfortable" dir="rtl" lang="ar">
49
+ <!-- application -->
50
+ </main>
51
+ ```
52
+
53
+ Theme, locale and text direction are independent. Use `dga` for the Platforms Code
54
+ palette or `custom` with your own documented CSS token overrides. Supply Arabic
55
+ labels, messages, tooltips, navigation labels, and result announcements explicitly.
56
+
57
+ ## Inputs and outputs
58
+
59
+ All value controls implement `ControlValueAccessor` for `ngModel` and
60
+ reactive forms. Alternatively, use `[(value)]`. Do not bind both on the same
61
+ control. Common inputs: `controlId`, `label`, `name`, `hint`, `error`, `required`,
62
+ `disabled`, `value`; output: `valueChange`. Errors and hints connect to the native
63
+ control through `aria-describedby`, and errors set `aria-invalid`. Use an
64
+ application-owned `controlId` when rendering on the server or depending on an ID.
65
+ `error` presents validation feedback; validation decisions belong to the form.
66
+ Use Angular's `resetForm()` / `FormGroup.reset()` to reset custom control values.
67
+
68
+ | Catalog entry / standalone export | Selector and specific API |
69
+ | --- | --- |
70
+ | Button — `HwButtonDirective` | `button[hwButton]`, `a[hwButton]`; `variant: primary/secondary/ghost/danger`, `size: sm/md/lg`. Native attributes/events/form semantics are preserved. Set button `type` explicitly; anchors require `href` and do not support disabled semantics. |
71
+ | Field — `HwFieldComponent` | `hw-field`; required `controlId`, `label`; optional `hint`, `error`. Project a native control with that ID and explicitly connect description IDs. |
72
+ | TextField — `HwTextFieldComponent` | `hw-text-field`; string value, `type`, `placeholder`, `autocomplete`, `inputmode`, `readOnly`; `size: sm/md/lg` (default md), `visualVariant: outline/filled` (default outline) style the native input. The native number input still emits a string; parse at your domain boundary. |
73
+ | Textarea — `HwTextareaComponent` | `hw-textarea`; string value, `rows`, `maxLength`, `placeholder`, `readOnly`; `size: sm/md/lg`, `visualVariant: outline/filled` style the native textarea. |
74
+ | Select — `HwSelectComponent` | `hw-select`; string value, `options: readonly Option[]`, `placeholder`; `size: sm/md/lg`, `visualVariant: outline/filled` style the native select. Native single select. |
75
+ | Checkbox — `HwCheckboxComponent` | `hw-checkbox`; boolean value, `indeterminate`. |
76
+ | Radio — `HwRadioComponent` | `hw-radio`; a named native radio group with a fieldset/legend, string value, `options`. |
77
+ | Switch — `HwSwitchComponent` | `hw-switch`; boolean value, native checkbox with switch role. |
78
+ | Combobox — `HwComboboxComponent` | `hw-combobox`; string value, `options`, `placeholder`, `emptyMessage`, `validationMessage`, `resultsMessage(count)`. Editable single selection; no async or virtualization. |
79
+ | Tabs — `HwTabsComponent`, `HwTabComponent` | `hw-tabs` contains `hw-tab`; tabs `label`, `id`, `[(value)]`, `orientation`, optional `direction`, `activationMode: automatic/manual`, `overflow: menu/scroll` (default menu), configurable `overflowLabel`. Each tab takes `value`, `label`, `disabled` and projects its panel. Compact horizontal containers disclose excess labels; vertical tabs remain visible. |
80
+ | Dialog — `HwDialogComponent` | `hw-dialog`; `title`, `titleId`, `[(open)]`, `closeLabel`, `closeOnBackdrop`; outputs `cancelled`, `returnValue`; methods `show(trigger?)`, `close(value?)`. Project content and `[hwDialogFooter]`. |
81
+ | Accordion — `HwAccordionComponent` | `hw-accordion`; `items: {id,title,content,open?}[]`, `exclusive`, `groupName`; `toggled: {id,open}`. Native details/summary. Project custom native details for richer content. |
82
+ | Card — `HwCardComponent` | `hw-card`; project `[hwCardHeader]`, body, `[hwCardFooter]`. |
83
+ | Badge — `HwBadgeComponent` | Static label; `tone="neutral\|success\|warning\|danger\|info"`, `variant="soft\|outline\|dot"`; [source and adaptations](../../docs/nic-badges.md). |
84
+ | Alert — `HwAlertComponent` | `hw-alert`; `title`, `tone: info/success/warning/danger`, `role: status/alert/region`, `dismissible`, `closeLabel`; `dismissed` asks the parent to remove it. |
85
+ | Table — `HwTableComponent` | `hw-table`; `caption`, `columns: {key,label,rowHeader?}[]`, `rows: Record<string,string\|number\|null\|undefined>[]`, `emptyMessage`. Values render as escaped text. |
86
+ | Pagination — `HwPaginationComponent` | `hw-pagination`; `[(page)]`, `totalPages`, Arabic default `label`, `previousLabel`, `nextLabel`, `pageLabel(page)`, `formatPage(page)`, `siblingCount=1`, `disabled`, `hideOnSinglePage=false`. Ellipsis disclosures use `gapLabel(start,end)`, `jumpLabel`, `goLabel`; gaps above 100 pages use bounded integer entry. Parent fetches/slices data; no navigation or scrolling is imposed. |
87
+ | Breadcrumb — `HwBreadcrumbComponent` | `hw-breadcrumb`; `items: {label,href?}[]`, `label`. Last item is current. |
88
+ | Progress — `HwProgressComponent` | `hw-progress`; `label`, `value: number\|null`, `max`; null is indeterminate. |
89
+ | Skeleton — `HwSkeletonComponent` | `hw-skeleton`; `width`, `height`; decorative, hidden from assistive technology. Announce surrounding loading state once. |
90
+ | Spinner — `HwSpinnerComponent` | `hw-spinner`; localized `label`; status announcement. |
91
+ | Avatar — `HwAvatarComponent` | Required `name`; optional `src`, `initials`, `size="40\|64\|80\|120\|sm\|md\|lg\|xl"`, `variant="circle\|square"`. Failed images fall back to initials; changing `src` retries. [Source notes](../../docs/nic-avatars.md). |
92
+ | Divider — `HwDividerComponent` | `hw-divider`; native horizontal rule. |
93
+ | Tooltip — `HwTooltipComponent` | `hw-tooltip`; `text`, `id`; project short noninteractive trigger content. Focusable trigger, hover/focus opening, Escape/outside closing. Do not project buttons or links into this focusable wrapper. |
94
+ | FileUpload — `HwFileUploadComponent` | `hw-file-upload`; readonly `File[]` value, `accept`, `multiple`. Selects local files only; no upload occurs. Forms can clear, but browsers forbid programmatically populating file pickers. |
95
+ | Stepper — `HwStepperComponent` | `hw-stepper`; `steps: {label,description?}[]`, zero-based `current`, `label`. Noninteractive progress list. |
96
+ | EmptyState — `HwEmptyStateComponent` | `hw-empty-state`; `title`, `description`, projected actions. |
97
+
98
+ ## Interaction guarantees
99
+
100
+ - Combobox options preserve values and display labels. Search normalization is
101
+ shared with core and folds Arabic diacritics/alef variants. Typing clears the
102
+ committed value. Arrow keys/Home/End move the active option, Enter explicitly
103
+ commits, and Escape/Tab/blur close without silently selecting. Unmatched query text fails native required validation; composition input and modified editing shortcuts are preserved. The input keeps
104
+ focus through `aria-activedescendant`. Disabled options cannot be committed.
105
+ - Tabs share core's wrapping navigation, skip disabled tabs, and follow RTL for
106
+ horizontal arrows. Manual activation uses native button Enter/Space. Panels
107
+ stay mounted; hidden panels leave the focus order.
108
+ - Dialog uses native `showModal()`/`close()` after view creation. Native modality,
109
+ focus containment and Escape behavior require a browser with dialog support.
110
+ Close and destruction restore the opening trigger when it remains connected.
111
+ No DOM globals are touched at module evaluation. A server render leaves the
112
+ dialog closed; the browser opens it during view initialization.
113
+ - The library imports no global CSS. HTML text is interpolated, never trusted HTML.
114
+ Theme selectors and CSS logical properties come from the shared style package.
115
+
116
+ ## Example and limits
117
+
118
+ `examples/angular` demonstrates a bilingual service discovery/application/review
119
+ flow, conditional guidance, file selection, and locally simulated request tracking.
120
+ It imports the built APF library and loads `@angular/compiler` intentionally for a
121
+ small Vite JIT demonstration. This is **not** a production Angular CLI AOT app,
122
+ server rendering proof, or hydration certification. Use the normal Angular build
123
+ pipeline for a production application. No request or file is submitted externally.
124
+
125
+ The current table API is textual, the accordion items API is textual, and the
126
+ combobox is local and single-select. For custom cells/details, compose the shared
127
+ CSS classes with native Angular templates rather than injecting HTML strings.
128
+
129
+ ## Expanded components
130
+
131
+ Every component below is standalone, exported as `Hw{Name}Component`, and uses
132
+ `hw-kebab-case` selectors. Value controls support both `[(ngModel)]`/reactive forms
133
+ and `[(value)]` (choose one), with inherited `controlId`, `label`, `name`, `hint`,
134
+ `error`, `required`, `disabled`, and `readOnly`. Angular form reset clears string
135
+ and array controls, empties NumberField, restores Slider to `min`, and RangeSlider
136
+ to `[min,max]`. Native range, radio, and checkbox controls retain browser keyboard
137
+ behavior. Readonly controls retain submitted values where HTML permits it.
138
+
139
+ | Component | Inputs, outputs and composition |
140
+ | --- | --- |
141
+ | InputGroup | Project `[hwPrefix]`, a labeled native/control input, and `[hwSuffix]`; `size: sm/md/lg`. Addons remain ordinary content, so label decorative icons appropriately. |
142
+ | PasswordField | String value; `autocomplete`, `placeholder`, `showLabel`, `hideLabel`. Reveal button keeps the same input and resets to hidden with forms. |
143
+ | SearchField | String value/CVA; `placeholder`, `autocomplete`, `autofocus`, `searchLabel`, `clearLabel`; optional `suggestions`, `maxSuggestions` (8), `resultsMessage(count)`, `showSearchButton` (true for compatibility); `searched(query)` output and public `focus()`. |
144
+ | NumberField | `number \| null` value; `min`, `max`, `step` (number or `any`). Empty/invalid native numeric input maps to null. Native step/min/max validation remains active. |
145
+ | Slider | Number value; `min`, `max`, `step`; native range plus value output. |
146
+ | RangeSlider | `[lower,upper]`; `min`, `max`, `step`, `lowerLabel`, `upperLabel`, `lowerName`, `upperName`. Crossing thumbs stop at the other value; absent distinct names, `name` submits two ordered values. |
147
+ | Rating | Numeric value, `max` (1–20), `ratingLabel(value,max)`; named native radio choices. |
148
+ | `HwRatingDisplayComponent / hw-rating-display` | Required `label`, numeric `value=0`, `max=5` (1–20), `showValue=true`, `valueLabel(value,max)`; noninteractive fractional aggregate score with one accessible image name. |
149
+ | PinInput | String value, `length`; one numeric input with `one-time-code` autocomplete, Arabic-Indic/Eastern Arabic digit normalization, paste support. |
150
+ | TagInput | `string[]`; `placeholder`, `addLabel`, `removeLabel`. Enter/comma or Add commits unique trimmed tags; repeated hidden form values. |
151
+ | MultiSelect | `string[]`; `options: Option[]`, `searchLabel`, `emptyMessage`, `selectedMessage(count)`, `validationMessage`. Searchable checkbox list; selected values remain in FormData when search hides their checkboxes. |
152
+ | Calendar | ISO Gregorian string value; `month`, `min`, `max`, `locale`, `calendar: gregory/islamic-umalqura`, `weekStartsOn`, `direction`, `previousLabel`, `nextLabel`; `monthChange`. Grid supports RTL-aware arrows, Home/End, PageUp/Down and Shift+PageUp/Down (year). Bounds restrict selection/focus. |
153
+ | DatePicker | ISO Gregorian value, a custom text field and modal calendar. Accepts Calendar localization and range inputs, `dialogTitle`, `openLabel`, `closeLabel`, `calendarLabel`, `gregorianLabel`, `hijriLabel` and `unsupportedMessage`. Switching emits `calendarChange` and preserves the selected ISO date. Opening returns to its month and day. |
154
+ | FileDropzone | `File[]`; `accept`, `multiple`, `instruction`, `selectedMessage(count)`; `rejected` emits rejected files. Native picker and local drop handling; no upload/network side effect. Browser `DataTransfer` support is needed to mirror dropped files into native FormData. Forms can clear files but cannot populate a picker from a stored path. |
155
+ | ToggleGroup | String value for single or `string[]` for `multiple`; `options`, `variant: segmented/outline`. Single uses native radios; multiple uses pressed buttons. |
156
+ | Popover | `label`, `triggerLabel`, `id`, `disabled`, `[(open)]`; project interactive content. Disclosure region with ordinary Tab order, outside press/Escape closing. |
157
+ | Menu | Popover inputs plus `items: {id,label,disabled?}[]`, `action(id)`. ArrowUp/Down/Home/End navigation skips disabled items; Escape/activation returns focus. |
158
+ | Drawer | Dialog inputs/outputs/methods plus `side: start/end/bottom`; project body and `[hwDrawerFooter]`. Native modal dialog. |
159
+ | ToastRegion | `messages: {id,title?,message,tone?,urgent?,dismissible?}[]`, `label`, `dismissLabel`, `(dismissed)="remove($event)"`. Set `variant="banner"` and optionally `position="inline"` or a corner. A dismissal listener enables the button. Defaults are Arabic. |
160
+ | Collapsible | `label`, `[(open)]`; native details/summary and projected body. |
161
+ | TreeView | String selection; `nodes: {id,label,disabled?,children?}[]`, `[(expandedIds)]`, `direction`. Roving focus, RTL arrows, Home/End, Enter/Space selection. Caller supplies unique IDs. |
162
+ | Carousel | Required label/slides; `[(current)]`, `loop=false`, `slides` and optional `slideTemplate` with `{ $implicit: HwSlide, index }`, one-based `slideLabel(index,total)`. `showIndicators=true`, localized control/indicator/description/empty labels, inert inactive slides, explicit navigation and no autoplay. [Source and motion notes](../../docs/nic-carousel.md). |
163
+ | Link | `href`, `target`, `rel`, `current`, `variant: default/subtle`; projected link text. `_blank` defaults to `noopener noreferrer`. |
164
+ | IconButton | Required accessible `label`; `type`, `disabled`, `pressed`, `variant`, `size`; `activated(MouseEvent)`. Project a decorative icon. |
165
+ | ButtonGroup | `label`, `orientation: horizontal/vertical`; project native buttons or IconButtons. |
166
+ | Chip | `tone`, `variant`, `removable`, `disabled`, `removeLabel`; `removed` asks the caller to remove it. |
167
+ | DescriptionList | `items: {term,description}[]`, `variant: stacked/horizontal`; project richer native dt/dd if needed. |
168
+ | Stat | `label`, `value`, `description`, `tone`; projected supplemental content. |
169
+ | Timeline | `label`, `items: {title,description?,time?,dateTime?,state?}[]`; state is complete/current/pending. |
170
+ | Meter | `label`, `value`, `min`, `max`, `low`, `high`, `optimum`; native meter for bounded measurements. |
171
+ | AvatarGroup | `label`, `avatars: {name,src?}[]`, `max`, `overflowLabel(count)`; named image/initials with overflow count. |
172
+ | DataTable | `caption`, `columns: {key,label,sortable?,rowHeader?}[]`, `rows: Record<string,string\|number\|boolean\|null\|undefined>[]`, `locale`, `emptyMessage`, `sortKey`, `sortDirection`; `sortChange({key,direction})`. Stable localized sorting, native headers and aria-sort; text cells. |
173
+ | ServiceCard | `title`, `href`, `description`, `category`, `duration`, `fee`, `actionLabel`, `variant`; project `[hwServiceIcon]` and supplemental body. |
174
+ | ServiceDetails | `title`, `description`, `details: {term,description}[]`, `requirements: string[]`, `requirementsLabel`; projected actions/content. |
175
+ | PortalHeader | `brand`, `homeHref`, `mainId`, `skipLabel`, `menuLabel`, `navigationLabel`, `navigationId`, `links: {label,href,current?}[]`; project `[hwBrand]` and header actions. Mobile menu is CSS-responsive; provide unique navigationId if repeated. Optional top-level `groups` contain a label and child links. See [grouped navigation](../../docs/nic-portal-navigation.md). |
176
+ | PortalFooter | `brand`, `copyright`, `navigationLabel`, `links`; projected supporting content. |
177
+ | Feedback | `label`, `positiveLabel`, `negativeLabel`, `thanksMessage`, `disabled`, `[(value)]` (boolean or null initially). Emits local feedback choice; caller handles storage. |
178
+ | CookieConsent | `title`, `description`, `acceptLabel`, `rejectLabel`, `preferencesLabel`, `[(visible)]`; `consent(accepted/rejected)` and `preferences`. Application decides persistence and script gating; this UI does not imply consent has been stored. |
179
+ | NotificationList | `label`, `items: {id,title,description?,time?,href?,unread?}[]`, `emptyMessage`, `unreadLabel`, `dismissLabel`; `dismissed(id)`. Caller owns read/dismiss state. |
180
+
181
+ The national platform patterns are configurable ordinary application content. They
182
+ provide no seals, government endorsement, identity verification or connected
183
+ service transactions. Strings are escaped Angular interpolation throughout.
184
+
185
+ ## Responsive composition
186
+
187
+ Container, Stack, Inline, Grid, Columns, Sidebar, Center, Spacer, AspectRatio,
188
+ Section, AppShell and PageHeader are native layout components. Shared props:
189
+ `gap`, `padding`, `align`, `justify`, `wrap`; spacing accepts token numbers 0–16
190
+ or CSS lengths. `gap`/`padding` and `columns` accept `{base,sm,md,lg,xl}` objects.
191
+ Breakpoints live in CSS (40/48/64/80rem), so server/client layout markup matches.
192
+
193
+ - Container: `maxWidth`.
194
+ - Grid/Columns: `columns`, `minItemWidth` (adaptive auto-fit).
195
+ - Sidebar: `sidebarWidth`, `side: start/end`, `collapseAt: sm/md/lg`; project
196
+ `[hwSidebar]` and main content. The main pane follows in DOM reading order.
197
+ - AspectRatio: numeric `ratio`, default 16/9. Spacer is decorative.
198
+ - Section: optional accessible `label`.
199
+ - AppShell accepts `mainId`, `skipLabel`, `sidebarWidth` and `side`. Project
200
+ `[hwShellHeader]`, `[hwShellSidebar]`, default main content and `[hwShellFooter]`.
201
+ The Arabic skip link focuses the main landmark, whose default ID is `main-content`.
202
+ Omitted regions leave the main area at full width.
203
+ - PageHeader: `title` (h1), `description`; `[hwBreadcrumb]` and default actions.
204
+
205
+ ```html
206
+ <hw-app-shell mainId="services" sidebarWidth="18rem">
207
+ <hw-portal-header hwShellHeader brand="بوابة الخدمات" mainId="services"
208
+ skipLabel="انتقل إلى المحتوى" menuLabel="القائمة" [links]="navigation" />
209
+ <nav hwShellSidebar aria-label="خدماتي"><!-- native links --></nav>
210
+ <hw-container maxWidth="80rem" [padding]="{base: 4, lg: 8}">
211
+ <hw-stack [gap]="6">
212
+ <hw-page-header title="الخدمات" description="ابحث وابدأ طلبك" />
213
+ <hw-grid [columns]="{base: 1, md: 2, xl: 3}" [gap]="4">
214
+ @for (service of services; track service.href) {
215
+ <hw-service-card [title]="service.title" [href]="service.href"
216
+ [description]="service.description" actionLabel="عرض الخدمة" />
217
+ }
218
+ </hw-grid>
219
+ <hw-date-picker name="date" label="التاريخ" [(ngModel)]="date"
220
+ [(calendar)]="calendar" locale="ar-SA" direction="rtl"
221
+ calendarLabel="التقويم" gregorianLabel="ميلادي" hijriLabel="هجري (أم القرى)"
222
+ openLabel="فتح التقويم" closeLabel="إغلاق التقويم"
223
+ previousLabel="الشهر السابق" nextLabel="الشهر التالي" />
224
+ </hw-stack>
225
+ </hw-container>
226
+ <hw-portal-footer hwShellFooter brand="بوابة الخدمات" />
227
+ </hw-app-shell>
228
+ ```
229
+
230
+ TextField additionally supports text/email/password/tel/url/search, native
231
+ number/range/color, and date/datetime-local/month/week/time. Its value remains a
232
+ string; date-related inputs return browser-defined ISO-like values, color returns
233
+ an HTML color, and number/range use numeric strings. `min`, `max`, `step`,
234
+ `minLength`, `maxLength`, and `pattern` forward native constraints where that input
235
+ type supports them. File, checkbox/radio, and form-action inputs have their own
236
+ purpose-built controls/native buttons. Use NumberField for `number | null` forms,
237
+ and DatePicker for switchable Gregorian/Umm al-Qura display with ISO storage.
238
+
239
+ The default Arabic locale supplies calendar navigation, picker control labels and validation messages. Set `locale="en"` for English or use individual label inputs for application-specific wording.
240
+
241
+ Calendar arithmetic comes from the shared core, `@internationalized/date`, and
242
+ the table-backed Saudi Umm al-Qura provider. Numeric Hijri dates, including
243
+ accessible day labels, come from that table rather than browser ICU conversion.
244
+ Umm al-Qura supports AH 1343–1500 (1924-08-01 through 2077-11-16); outside this
245
+ interval DatePicker retains the ISO value and presents `unsupportedMessage`,
246
+ while Gregorian entry remains available. Calendar edge navigation stays bounded. Locale and calendar do not determine
247
+ text direction. Calendar bounds and the verified Umm al-Qura supported interval
248
+ follow the shared core's documented contract.
249
+
250
+ Maps, rich-text editors, charts, code editors, PDF viewers, CAPTCHA and payments
251
+ remain integration boundaries. Compose their provider SDKs in Card/Section/Grid,
252
+ provide accessible fallbacks, and keep credentials and payment/identity actions
253
+ in the application. DataTable has no editing or virtualization; TreeView has no
254
+ drag/drop; these APIs make no claim to supply those larger engines.
255
+
256
+ ## Portal shell
257
+
258
+ [`HwPortalLayoutComponent` and `HwSecondaryNavComponent`](PORTAL.md) provide a
259
+ complete Arabic-default portal shell with responsive navigation and footer.
260
+ Run the Angular example with `?preview=portal` to use the native composed shell.
261
+
262
+ ## NIC card composition
263
+
264
+ See [cards](../../docs/nic-cards.md) for source-mapped spacing, variants, whole-card links, disabled semantics and content classes. Native framework consumers include `?preview=nic`; vanilla uses the documented semantic HTML recipe.
265
+
266
+ See [NIC button variants](../../docs/nic-buttons.md) for all ten appearances,
267
+ interaction states, dark-surface use and density adaptations.
268
+
269
+ [Ready component examples](../../docs/ready-component-examples.md) cover all five
270
+ alert/notification tones, header/footer composition and guide-only navigation containment.
271
+
272
+ InputGroup tracks value presence for projected native `.hw-input` / `.hw-select`
273
+ controls after Angular renders; no vanilla enhancer is required. Keep labels
274
+ and hints outside the joined row. See [NIC input composition](../../docs/nic-inputs.md).
275
+ # Native choice read-only state
276
+
277
+ `HwCheckboxComponent`, `HwRadioComponent` and `HwSwitchComponent` accept `readOnly`.
278
+ The control remains keyboard-focusable and submits its value, while pointer and
279
+ keyboard activation leave its value and radio peers unchanged. Disabled remains
280
+ a separate native state. See [NIC states](../../docs/nic-choices.md).
281
+
282
+
283
+ [Site verification](../../docs/site-verification.md) composes a native disclosure above the header with deployment-owned domain and certificate information. [Grouped portal footers](../../docs/nic-footer.md) add navigation groups, support actions, legal links and identity slots.
284
+
285
+ [Link and breadcrumb states](../../docs/nic-links.md) document neutral/standalone variants, disabled destinations, source contrast substitutions and native adapter APIs.
286
+
287
+
288
+ ### Table presentation and empty results
289
+
290
+ `Table` and `DataTable` expose `variant="default|striped|bordered"`,
291
+ `size="sm|md|lg"` and `emptyMessage`. DGA cells have a 48px default minimum;
292
+ 40px/56px alternate sizes and striped/bordered variants are Hawiyah extensions.
293
+ Captions name keyboard-focusable horizontal scroll containers; row-header
294
+ columns render native `th scope="row"`. Empty data spans the column count and
295
+ uses an Arabic message by default. Sorting does not mutate caller records.
296
+ The default sort locale is `ar-SA`. Both component hosts shrink inside grid/flex
297
+ layouts so overflow stays inside the table wrapper.
298
+ See [table evidence and adaptations](../../docs/nic-tables.md).
299
+
300
+ Rating inputs select whole numbers; finite prefilled values are clamped to the normalized maximum and floored. Fractional averages belong in `RatingDisplay`. Nonfinite maxima fall back to 5 and nonfinite values to 0. Arabic labels and Latin digits are the defaults.
301
+
302
+
303
+ ### Search suggestions
304
+
305
+ SearchField accepts local string suggestions and remains a free-text input.
306
+ With suggestions supplied it exposes an editable combobox/listbox, highlighted
307
+ matches and a polite result count. Arrow keys wrap through matches; Enter on an
308
+ active suggestion selects it and prevents form submission. Ordinary Enter with
309
+ no active suggestion emits `searched` with a trimmed, nonempty query and keeps
310
+ native form submission available. Choose either the search callback or the
311
+ form's submit handler for the application request; wiring both duplicates it.
312
+ The optional icon search action is a non-submit button and uses the callback.
313
+ Arabic clear/search labels are defaults and can be localized.
314
+
315
+ Escape dismisses an open list before reaching an enclosing dialog; another
316
+ Escape can dismiss the dialog. Composition/modifier keys do not commit matches.
317
+ Readonly inputs remain searchable but cannot edit/clear/select suggestions;
318
+ disabled inputs cannot search. Blur, outside press, reset and changed suggestion
319
+ configuration clear active-option state. No remote search service is called.
320
+
321
+ ### Content navigation
322
+
323
+ `HwContentNavigationComponent` (`hw-content-navigation`) follows application-owned section IDs using nested
324
+ `items: {id, label, disabled?, children?}[]`. Options are `label` (Arabic default),
325
+ `showHeading` (true), `sticky` (false), `scrollRoot` (null/window) and `offset`
326
+ (80px). `(currentChange)="onCurrentChange($event)"` reports the current section ID. Ordinary
327
+ activation scrolls without changing the URL; keyboard activation also focuses
328
+ the target. Modified anchor clicks retain browser behavior. Disabled entries
329
+ remain noninteractive text links; no section content is created or hidden.
330
+
331
+ ```html
332
+ <!-- Add HwContentNavigationComponent to the host component's imports. -->
333
+ <hw-content-navigation [items]="[{id: 'requirements', label: 'المتطلبات'}]" />
334
+ <section id="requirements"><h2>المتطلبات</h2></section>
335
+ ```