@almadar/ui 5.8.0 → 5.9.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.
@@ -28234,6 +28234,311 @@ var init_Lightbox = __esm({
28234
28234
  Lightbox.displayName = "Lightbox";
28235
28235
  }
28236
28236
  });
28237
+ function columnLabel(col) {
28238
+ return col.header ?? col.label ?? col.key.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/[_-]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
28239
+ }
28240
+ function statusVariant4(value) {
28241
+ const v = value.toLowerCase();
28242
+ if (["active", "completed", "done", "approved", "published", "resolved", "open", "online", "ok"].includes(v)) return "success";
28243
+ if (["pending", "in_progress", "in-progress", "review", "draft", "processing", "warn", "warning"].includes(v)) return "warning";
28244
+ if (["inactive", "deleted", "rejected", "failed", "error", "blocked", "closed", "offline"].includes(v)) return "error";
28245
+ if (["new", "created", "scheduled", "queued", "info"].includes(v)) return "info";
28246
+ return "default";
28247
+ }
28248
+ function formatCell(value, format) {
28249
+ if (value === void 0 || value === null) return "";
28250
+ switch (format) {
28251
+ case "date": {
28252
+ const d = new Date(String(value));
28253
+ return isNaN(d.getTime()) ? String(value) : d.toLocaleDateString(void 0, { year: "numeric", month: "short", day: "numeric" });
28254
+ }
28255
+ case "currency":
28256
+ return typeof value === "number" ? `$${value.toFixed(2)}` : String(value);
28257
+ case "number":
28258
+ return typeof value === "number" ? value.toLocaleString() : String(value);
28259
+ case "percent":
28260
+ return typeof value === "number" ? `${Math.round(value)}%` : String(value);
28261
+ case "boolean":
28262
+ return value ? "Yes" : "No";
28263
+ default:
28264
+ return String(value);
28265
+ }
28266
+ }
28267
+ function groupData2(items, field) {
28268
+ const groups = /* @__PURE__ */ new Map();
28269
+ for (const item of items) {
28270
+ const key = String(getNestedValue(item, field) ?? "");
28271
+ const group = groups.get(key);
28272
+ if (group) group.push(item);
28273
+ else groups.set(key, [item]);
28274
+ }
28275
+ return Array.from(groups.entries()).map(([label, groupItems]) => ({ label, items: groupItems }));
28276
+ }
28277
+ function TableView({
28278
+ entity,
28279
+ columns,
28280
+ fields,
28281
+ itemActions,
28282
+ selectable = false,
28283
+ selectEvent,
28284
+ selectedIds,
28285
+ sortEvent,
28286
+ sortColumn,
28287
+ sortDirection,
28288
+ className,
28289
+ emptyMessage,
28290
+ isLoading = false,
28291
+ error = null,
28292
+ groupBy,
28293
+ pageSize = 0,
28294
+ children,
28295
+ renderItem: _schemaRenderItem,
28296
+ look = "dense",
28297
+ // DnD props consumed by useDataDnd.
28298
+ dragGroup,
28299
+ accepts,
28300
+ sortable,
28301
+ dropEvent,
28302
+ reorderEvent,
28303
+ positionEvent,
28304
+ dndItemIdField,
28305
+ dndRoot
28306
+ }) {
28307
+ const eventBus = useEventBus();
28308
+ const { t } = useTranslate();
28309
+ const [visibleCount, setVisibleCount] = React80__default.useState(pageSize > 0 ? pageSize : Infinity);
28310
+ const [localSelected, setLocalSelected] = React80__default.useState(/* @__PURE__ */ new Set());
28311
+ const colDefs = columns ?? fields ?? [];
28312
+ const allDataRaw = Array.isArray(entity) ? entity : entity ? [entity] : [];
28313
+ const dnd = useDataDnd({
28314
+ items: allDataRaw,
28315
+ layout: "list",
28316
+ dragGroup,
28317
+ accepts,
28318
+ sortable,
28319
+ dropEvent,
28320
+ reorderEvent,
28321
+ positionEvent,
28322
+ dndItemIdField,
28323
+ dndRoot
28324
+ });
28325
+ const ordered = dnd.orderedItems;
28326
+ const data = pageSize > 0 ? ordered.slice(0, visibleCount) : ordered;
28327
+ const hasMore = pageSize > 0 && visibleCount < ordered.length;
28328
+ const hasRenderProp = typeof children === "function";
28329
+ const idField = dndItemIdField ?? "id";
28330
+ const selected = selectedIds ? new Set(selectedIds) : localSelected;
28331
+ const emitSelection = (next) => {
28332
+ if (!selectedIds) setLocalSelected(next);
28333
+ if (selectEvent) {
28334
+ const payload = { selectedIds: Array.from(next) };
28335
+ eventBus.emit(`UI:${selectEvent}`, payload);
28336
+ }
28337
+ };
28338
+ const allSelected = selectable && data.length > 0 && data.every((r, i) => selected.has(String(r[idField] ?? i)));
28339
+ const toggleAll = () => {
28340
+ if (allSelected) emitSelection(/* @__PURE__ */ new Set());
28341
+ else emitSelection(new Set(data.map((r, i) => String(r[idField] ?? i))));
28342
+ };
28343
+ const toggleRow = (id) => {
28344
+ const next = new Set(selected);
28345
+ if (next.has(id)) next.delete(id);
28346
+ else next.add(id);
28347
+ emitSelection(next);
28348
+ };
28349
+ const handleSort = (col) => {
28350
+ if (!col.sortable || !sortEvent) return;
28351
+ const dir = sortColumn === (col.field ?? col.key) && sortDirection === "asc" ? "desc" : "asc";
28352
+ eventBus.emit(`UI:${sortEvent}`, { column: col.field ?? col.key, direction: dir });
28353
+ };
28354
+ const handleActionClick = (action, row) => (e) => {
28355
+ e.stopPropagation();
28356
+ const payload = {
28357
+ id: row.id,
28358
+ row
28359
+ };
28360
+ eventBus.emit(`UI:${action.event}`, payload);
28361
+ };
28362
+ if (isLoading) {
28363
+ return /* @__PURE__ */ jsx(Box, { className: "text-center py-8", children: /* @__PURE__ */ jsx(Typography, { variant: "body", color: "secondary", children: t("loading.items") || "Loading\u2026" }) });
28364
+ }
28365
+ if (error) {
28366
+ return /* @__PURE__ */ jsx(Box, { className: "text-center py-8", children: /* @__PURE__ */ jsx(Typography, { variant: "body", color: "error", children: error.message }) });
28367
+ }
28368
+ if (data.length === 0) {
28369
+ const emptyNode = /* @__PURE__ */ jsx(Box, { className: "text-center py-12", children: /* @__PURE__ */ jsx(Typography, { variant: "body", color: "secondary", children: emptyMessage || t("empty.noItems") || "No records" }) });
28370
+ return dnd.enabled ? /* @__PURE__ */ jsx(Fragment, { children: dnd.wrapContainer(emptyNode) }) : emptyNode;
28371
+ }
28372
+ const lk = LOOKS[look];
28373
+ const header = /* @__PURE__ */ jsxs(
28374
+ Box,
28375
+ {
28376
+ role: "row",
28377
+ className: cn(
28378
+ "flex items-center gap-3 sticky top-0 z-10",
28379
+ "bg-[var(--color-surface-subtle)] border-b border-[var(--color-table-border)]",
28380
+ "text-[var(--color-text-muted)] uppercase text-xs font-semibold tracking-wide",
28381
+ lk.headPad
28382
+ ),
28383
+ children: [
28384
+ selectable && /* @__PURE__ */ jsx(Box, { className: "w-8 flex-shrink-0 flex items-center", children: /* @__PURE__ */ jsx(Checkbox, { checked: allSelected, onChange: toggleAll, "aria-label": "Select all rows" }) }),
28385
+ colDefs.map((col) => {
28386
+ const active = sortColumn === (col.field ?? col.key);
28387
+ return /* @__PURE__ */ jsxs(
28388
+ Box,
28389
+ {
28390
+ role: "columnheader",
28391
+ onClick: () => handleSort(col),
28392
+ className: cn(
28393
+ "flex items-center gap-1 min-w-0",
28394
+ col.width ?? "flex-1",
28395
+ alignClass[col.align ?? "left"],
28396
+ col.sortable && sortEvent && "cursor-pointer select-none hover:text-foreground"
28397
+ ),
28398
+ children: [
28399
+ col.icon && /* @__PURE__ */ jsx(Icon, { name: col.icon, size: "xs" }),
28400
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: columnLabel(col) }),
28401
+ col.sortable && sortEvent && /* @__PURE__ */ jsx(
28402
+ Icon,
28403
+ {
28404
+ name: active ? sortDirection === "asc" ? "chevron-up" : "chevron-down" : "chevrons-up-down",
28405
+ size: "xs",
28406
+ className: cn("flex-shrink-0", active ? "text-foreground" : "opacity-40")
28407
+ }
28408
+ )
28409
+ ]
28410
+ },
28411
+ col.key
28412
+ );
28413
+ }),
28414
+ itemActions && itemActions.length > 0 && /* @__PURE__ */ jsx(Box, { className: "w-px flex-shrink-0", "aria-hidden": true })
28415
+ ]
28416
+ }
28417
+ );
28418
+ const renderRow = (row, index) => {
28419
+ const id = String(row[idField] ?? index);
28420
+ const rowInner = /* @__PURE__ */ jsxs(
28421
+ Box,
28422
+ {
28423
+ role: "row",
28424
+ "data-entity-row": true,
28425
+ "data-entity-id": id,
28426
+ className: cn(
28427
+ "group flex items-center gap-3 transition-colors duration-fast",
28428
+ lk.rowPad,
28429
+ lk.divider && "border-b border-[var(--color-table-border)]",
28430
+ lk.striped && index % 2 === 1 && "bg-[var(--color-surface-subtle)]",
28431
+ "hover:bg-[var(--color-surface-subtle)]",
28432
+ look === "bordered" && "[&>*]:border-r [&>*]:border-[var(--color-table-border)] [&>*:last-child]:border-r-0"
28433
+ ),
28434
+ children: [
28435
+ selectable && /* @__PURE__ */ jsx(Box, { className: "w-8 flex-shrink-0 flex items-center", children: /* @__PURE__ */ jsx(
28436
+ Checkbox,
28437
+ {
28438
+ checked: selected.has(id),
28439
+ onChange: () => toggleRow(id),
28440
+ "aria-label": `Select row ${id}`
28441
+ }
28442
+ ) }),
28443
+ hasRenderProp ? /* @__PURE__ */ jsx(Box, { className: "flex-1 min-w-0", children: children(row, index) }) : colDefs.map((col) => {
28444
+ const raw = getNestedValue(row, col.field ?? col.key);
28445
+ const cellBase = cn(
28446
+ "flex items-center min-w-0",
28447
+ col.width ?? "flex-1",
28448
+ alignClass[col.align ?? "left"],
28449
+ weightClass[col.weight ?? "normal"],
28450
+ col.className
28451
+ );
28452
+ if (col.format === "badge" && raw != null && raw !== "") {
28453
+ return /* @__PURE__ */ jsx(Box, { role: "cell", className: cellBase, children: /* @__PURE__ */ jsx(Badge, { variant: statusVariant4(String(raw)), size: "sm", children: String(raw) }) }, col.key);
28454
+ }
28455
+ return /* @__PURE__ */ jsx(Box, { role: "cell", className: cn(cellBase, "truncate block"), children: formatCell(raw, col.format) }, col.key);
28456
+ }),
28457
+ itemActions && itemActions.length > 0 && /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "flex-shrink-0 opacity-60 group-hover:opacity-100 transition-opacity", children: itemActions.map((action, i) => /* @__PURE__ */ jsxs(
28458
+ Button,
28459
+ {
28460
+ variant: action.variant ?? "ghost",
28461
+ size: "sm",
28462
+ onClick: handleActionClick(action, row),
28463
+ "data-testid": `action-${action.event}`,
28464
+ "data-row-id": String(row.id),
28465
+ className: cn(action.variant === "danger" && "text-error hover:bg-error/10"),
28466
+ children: [
28467
+ action.icon && /* @__PURE__ */ jsx(Icon, { name: action.icon, size: "xs", className: "mr-1" }),
28468
+ action.label
28469
+ ]
28470
+ },
28471
+ i
28472
+ )) })
28473
+ ]
28474
+ }
28475
+ );
28476
+ return dnd.isZone ? /* @__PURE__ */ jsx(dnd.SortableItem, { id: row[idField] ?? id, children: rowInner }, id) : /* @__PURE__ */ jsx(React80__default.Fragment, { children: rowInner }, id);
28477
+ };
28478
+ const items = data.map((row) => row);
28479
+ const groups = groupBy ? groupData2(items, groupBy) : [{ label: "", items }];
28480
+ let runningIndex = 0;
28481
+ const body = /* @__PURE__ */ jsx(Box, { role: "rowgroup", children: groups.map((group, gi) => /* @__PURE__ */ jsxs(React80__default.Fragment, { children: [
28482
+ group.label && /* @__PURE__ */ jsx(Divider, { label: group.label, className: gi > 0 ? "mt-3" : "mt-0" }),
28483
+ group.items.map((row) => renderRow(row, runningIndex++))
28484
+ ] }, gi)) });
28485
+ return /* @__PURE__ */ jsxs(
28486
+ Box,
28487
+ {
28488
+ role: "table",
28489
+ className: cn("w-full text-sm", className),
28490
+ children: [
28491
+ header,
28492
+ dnd.wrapContainer(body),
28493
+ hasMore && /* @__PURE__ */ jsx(Box, { className: "flex justify-center py-3", children: /* @__PURE__ */ jsxs(Button, { variant: "ghost", size: "sm", onClick: () => setVisibleCount((p2) => p2 + (pageSize || 5)), children: [
28494
+ /* @__PURE__ */ jsx(Icon, { name: "chevron-down", size: "xs", className: "mr-1" }),
28495
+ t("common.showMore"),
28496
+ " (",
28497
+ ordered.length - visibleCount,
28498
+ " remaining)"
28499
+ ] }) })
28500
+ ]
28501
+ }
28502
+ );
28503
+ }
28504
+ var alignClass, weightClass, LOOKS;
28505
+ var init_TableView = __esm({
28506
+ "components/molecules/TableView.tsx"() {
28507
+ "use client";
28508
+ init_cn();
28509
+ init_getNestedValue();
28510
+ init_useEventBus();
28511
+ init_useTranslate();
28512
+ init_Box();
28513
+ init_Stack();
28514
+ init_Typography();
28515
+ init_Badge();
28516
+ init_Button();
28517
+ init_Icon();
28518
+ init_Checkbox();
28519
+ init_Divider();
28520
+ init_useDataDnd();
28521
+ createLogger("almadar:ui:table-view");
28522
+ alignClass = {
28523
+ left: "justify-start text-left",
28524
+ center: "justify-center text-center",
28525
+ right: "justify-end text-right"
28526
+ };
28527
+ weightClass = {
28528
+ normal: "",
28529
+ medium: "font-medium",
28530
+ semibold: "font-semibold"
28531
+ };
28532
+ LOOKS = {
28533
+ dense: { rowPad: "px-3 py-2", headPad: "px-3 py-2", striped: false, divider: true },
28534
+ spacious: { rowPad: "px-5 py-4", headPad: "px-5 py-3", striped: false, divider: true },
28535
+ striped: { rowPad: "px-3 py-2", headPad: "px-3 py-2", striped: true, divider: false },
28536
+ borderless: { rowPad: "px-3 py-2", headPad: "px-3 py-2", striped: false, divider: false },
28537
+ bordered: { rowPad: "px-3 py-2", headPad: "px-3 py-2", striped: false, divider: true }
28538
+ };
28539
+ TableView.displayName = "TableView";
28540
+ }
28541
+ });
28237
28542
  function formatNumber(value, format) {
28238
28543
  if (value == null) return "0";
28239
28544
  const v = typeof value === "number" ? value : value;
@@ -33924,6 +34229,7 @@ var init_molecules = __esm({
33924
34229
  init_Lightbox();
33925
34230
  init_DataGrid();
33926
34231
  init_DataList();
34232
+ init_TableView();
33927
34233
  init_StatDisplay();
33928
34234
  init_Meter();
33929
34235
  init_SwipeableRow();
@@ -41386,7 +41692,7 @@ function VerifyModePanel({
41386
41692
  }
41387
41693
  prevCountRef.current = transitions.length;
41388
41694
  }, [transitions.length, expanded]);
41389
- const hudBottom = typeof document !== "undefined" ? document.getElementById("runtime-debugger-portal") ?? document.getElementById("slot-hud-bottom") : null;
41695
+ const hudBottom = typeof document !== "undefined" ? document.getElementById("runtime-debugger-portal") : null;
41390
41696
  const panel = /* @__PURE__ */ jsxs(
41391
41697
  "div",
41392
41698
  {
@@ -45925,6 +46231,7 @@ var init_component_registry_generated = __esm({
45925
46231
  init_Switch();
45926
46232
  init_TabbedContainer();
45927
46233
  init_Table();
46234
+ init_TableView();
45928
46235
  init_Tabs();
45929
46236
  init_TagCloud();
45930
46237
  init_TagInput();
@@ -46242,6 +46549,7 @@ var init_component_registry_generated = __esm({
46242
46549
  "Switch": Switch,
46243
46550
  "TabbedContainer": TabbedContainer,
46244
46551
  "Table": Table,
46552
+ "TableView": TableView,
46245
46553
  "Tabs": Tabs,
46246
46554
  "TagCloud": TagCloud,
46247
46555
  "TagInput": TagInput,
@@ -47358,7 +47666,7 @@ var FormActions = ({
47358
47666
  align = "right",
47359
47667
  className
47360
47668
  }) => {
47361
- const alignClass = {
47669
+ const alignClass2 = {
47362
47670
  left: "justify-start",
47363
47671
  right: "justify-end",
47364
47672
  between: "justify-between",
@@ -47371,7 +47679,7 @@ var FormActions = ({
47371
47679
  align: "center",
47372
47680
  className: cn(
47373
47681
  "pt-6 border-t border-border",
47374
- alignClass,
47682
+ alignClass2,
47375
47683
  sticky && "sticky bottom-0 bg-card py-4 -mx-6 px-6 shadow-[0_-4px_6px_-1px_rgb(0,0,0,0.05)]",
47376
47684
  className
47377
47685
  ),
@@ -50153,4 +50461,4 @@ function useGitHubBranches(owner, repo, enabled = true) {
50153
50461
  });
50154
50462
  }
50155
50463
 
50156
- export { ALL_PRESETS, ALMADAR_DND_MIME, AR_BOOK_FIELDS, AboutPageTemplate, Accordion, ActionButton, ActionButtons, Card2 as ActionCard, ActionPalette, ActionTile, Alert, AnimatedCounter, AnimatedGraphic, AnimatedReveal, ArticleSection, Aside, AuthLayout, Avatar, Badge, BattleBoard, BattleTemplate, BehaviorView, BookChapterView, BookCoverPage, BookNavBar, BookTableOfContents, BookViewer, Box, BranchingLogicBuilder, Breadcrumb, BuilderBoard, Button, ButtonGroup, CTABanner, CalendarGrid, CanvasEffect, Card, CardBody, CardContent, CardFooter, CardGrid, CardHeader, CardTitle, Carousel, CaseStudyCard, CaseStudyOrganism, CastleBoard, CastleTemplate, Center, Chart, ChartLegend, Checkbox, ChoiceButton, ClassifierBoard, CodeBlock, CodeExample, CodeView, CodeViewer, CollapsibleSection, CombatLog, ComboCounter, CommunityLinks, ConditionalWrapper, ConfettiEffect, ConfirmDialog, Container, ContentRenderer, ContentSection, ControlButton, CounterTemplate, CraftingRecipe, DEFAULT_LIKERT_OPTIONS, DEFAULT_MATRIX_COLUMNS, DEFAULT_SLOTS, DIAMOND_TOP_Y, DPad, DamageNumber, DashboardGrid, DashboardLayout, DataGrid, DataList, DataTable, DateRangePicker, DateRangeSelector, DayCell, DebuggerBoard, DetailPanel, Dialog, DialogueBox, DialogueBubble, Divider, DocBreadcrumb, DocCodeBlock, DocPagination, DocSearch, DocSidebar, DocTOC, DocumentViewer, StateMachineView as DomStateMachineVisualizer, Drawer, DrawerSlot, EdgeDecoration, EditorCheckbox, EditorSelect, EditorSlider, EditorTextInput, EditorToolbar, EmptyState, EnemyPlate, EntityDisplayEvents, ErrorBoundary, ErrorState, EventHandlerBoard, EventLog, FEATURE_COLORS, FEATURE_TYPES, FLOOR_HEIGHT, FeatureCard, FeatureDetailPageTemplate, FeatureGrid, FeatureGridOrganism, FeatureRenderer2 as FeatureRenderer, FileTree, FilterGroup, FilterPill, Flex, FlipCard, FlipContainer, FloatingActionButton, Form, FormActions, FormField, FormLayout, FormSection, FormSectionHeader, GameAudioContext, GameAudioProvider, GameAudioToggle, GameCanvas2D, GameHud, GameMenu, GameOverScreen, GameShell, GameTemplate, GenericAppTemplate, GeometricPattern, GradientDivider, GraphCanvas, GraphView, Grid, HStack, Header, Heading, HealthBar, HealthPanel, HeroOrganism, HeroSection, I18nProvider, IDENTITY_BOOK_FIELDS, Icon, InfiniteScrollSentinel, Input, InputGroup, InstallBox, InventoryGrid, InventoryPanel, IsometricCanvas, ItemSlot, JazariStateMachine, Label, LandingPageTemplate, LawReferenceTooltip, Lightbox, LikertScale, LineChart2 as LineChart, List3 as List, LoadingState, MapView, MarkdownContent, MarketingFooter, MarketingStatCard, MasterDetail, MasterDetailLayout, MatrixQuestion, MediaGallery, Menu, Meter, MiniMap, Modal, ModalSlot, ModuleCard, Navigation, NegotiatorBoard, NotifyListener, NumberStepper, ObjectRulePanel, OptionConstraintGroup, StateMachineView as OrbitalStateMachineView, OrbitalVisualization, Overlay, PageHeader, Pagination, PatternTile, PhysicsManager, PlatformerCanvas, Popover, PositionedCanvas, PowerupSlots, PricingCard, PricingGrid, PricingOrganism, PricingPageTemplate, ProgressBar, ProgressDots, PullQuote, PullToRefresh, QrScanner, QuestTracker, QuizBlock, Radio, RangeSlider, RelationSelect, RepeatableFormSection, ReplyTree, ResourceBar, ResourceCounter, RichBlockEditor, RuleEditor, RuntimeDebugger, SHEET_COLUMNS, SPRITE_SHEET_LAYOUT, ScaledDiagram, ScoreBoard, ScoreDisplay, SearchInput, Section, SectionHeader, Select, SequenceBar, SequencerBoard, ServiceCatalog, ShowcaseCard, ShowcaseOrganism, SidePanel, Sidebar, SignaturePad, SimpleGrid, SimulationCanvas, SimulationControls, SimulationGraph, SimulatorBoard, Skeleton, SlotContentRenderer, SocialProof, SortableList, Spacer, Sparkline, Spinner, Split, SplitPane, SplitSection, Sprite, Stack, StarRating, StatBadge, StatCard, StatDisplay, StateArchitectBoard, StateIndicator, StateMachineView, StateNode2 as StateNode, StatsGrid, StatsOrganism, StatusBar, StatusDot, StatusEffect, StepFlow, StepFlowOrganism, SvgBranch, SvgConnection, SvgFlow, SvgGrid, SvgLobe, SvgMesh, SvgMorph, SvgNode, SvgPulse, SvgRing, SvgShield, SvgStack, SwipeableRow, Switch, TERRAIN_COLORS, TILE_HEIGHT, TILE_WIDTH, TabbedContainer, Table, Tabs, TagCloud, TagInput, TeamCard, TeamOrganism, TerrainPalette, Text, TextHighlight, Textarea, ThemeSelector, ThemeToggle, TimeSlotCell, Timeline, TimerDisplay, Toast, ToastSlot, Tooltip, TraitFrame, TraitSlot, TraitStateViewer, TransitionArrow, TrendIndicator, TurnIndicator, TurnPanel, TypewriterText, Typography, UISlotComponent, UISlotRenderer, UncontrolledBattleBoard, UnitCommandBar, UploadDropZone, VStack, VariablePanel, VersionDiff, ViolationAlert, VoteStack, WaypointMarker, WizardContainer, WizardNavigation, WizardProgress, WorldMapBoard, WorldMapTemplate, XPBar, applyTemporaryEffect, calculateAttackTargets, calculateDamage, calculateValidMoves, clearEntities, cn, combatAnimations, combatClasses, combatEffects, createInitialGameState, createTranslate, createUnitAnimationState, drawSprite, generateCombatMessage, getAllEntities, getByType, getCurrentFrame, getEntity, getSingleton, getTileDimensions, inferDirection, isoToScreen, mapBookData, parseQueryBinding, pendulum, projectileMotion, removeEntity, resolveFieldMap, resolveFrame, resolveSheetDirection, screenToIso, spawnEntity, springOscillator, tickAnimationState, transitionAnimation, updateEntity, updateSingleton, useAgentChat, useAuthContext, useBattleState, useCamera, useCompile, useConnectGitHub, useDeepAgentGeneration, useDisconnectGitHub, useDragReorder, useDraggable, useDropZone, useEmitEvent, useEntities, useEntitiesByType, useEntity as useEntityById, useEventBus, useEventListener, useExtensions, useFileEditor, useFileSystem, useGameAudio, useGameAudioContext, useGitHubBranches, useGitHubRepo, useGitHubRepos, useGitHubStatus, useImageCache, useInfiniteScroll, useInput, useLongPress, useOrbitalHistory, usePhysics, usePhysics2D, usePinchZoom, usePlayer, usePreview, usePullToRefresh, useQuerySingleton, useSingletonEntity, useSpriteAnimations, useSwipeGesture, useTraitListens, useTranslate, useUIEvents, useUISlotManager, useValidation };
50464
+ export { ALL_PRESETS, ALMADAR_DND_MIME, AR_BOOK_FIELDS, AboutPageTemplate, Accordion, ActionButton, ActionButtons, Card2 as ActionCard, ActionPalette, ActionTile, Alert, AnimatedCounter, AnimatedGraphic, AnimatedReveal, ArticleSection, Aside, AuthLayout, Avatar, Badge, BattleBoard, BattleTemplate, BehaviorView, BookChapterView, BookCoverPage, BookNavBar, BookTableOfContents, BookViewer, Box, BranchingLogicBuilder, Breadcrumb, BuilderBoard, Button, ButtonGroup, CTABanner, CalendarGrid, CanvasEffect, Card, CardBody, CardContent, CardFooter, CardGrid, CardHeader, CardTitle, Carousel, CaseStudyCard, CaseStudyOrganism, CastleBoard, CastleTemplate, Center, Chart, ChartLegend, Checkbox, ChoiceButton, ClassifierBoard, CodeBlock, CodeExample, CodeView, CodeViewer, CollapsibleSection, CombatLog, ComboCounter, CommunityLinks, ConditionalWrapper, ConfettiEffect, ConfirmDialog, Container, ContentRenderer, ContentSection, ControlButton, CounterTemplate, CraftingRecipe, DEFAULT_LIKERT_OPTIONS, DEFAULT_MATRIX_COLUMNS, DEFAULT_SLOTS, DIAMOND_TOP_Y, DPad, DamageNumber, DashboardGrid, DashboardLayout, DataGrid, DataList, DataTable, DateRangePicker, DateRangeSelector, DayCell, DebuggerBoard, DetailPanel, Dialog, DialogueBox, DialogueBubble, Divider, DocBreadcrumb, DocCodeBlock, DocPagination, DocSearch, DocSidebar, DocTOC, DocumentViewer, StateMachineView as DomStateMachineVisualizer, Drawer, DrawerSlot, EdgeDecoration, EditorCheckbox, EditorSelect, EditorSlider, EditorTextInput, EditorToolbar, EmptyState, EnemyPlate, EntityDisplayEvents, ErrorBoundary, ErrorState, EventHandlerBoard, EventLog, FEATURE_COLORS, FEATURE_TYPES, FLOOR_HEIGHT, FeatureCard, FeatureDetailPageTemplate, FeatureGrid, FeatureGridOrganism, FeatureRenderer2 as FeatureRenderer, FileTree, FilterGroup, FilterPill, Flex, FlipCard, FlipContainer, FloatingActionButton, Form, FormActions, FormField, FormLayout, FormSection, FormSectionHeader, GameAudioContext, GameAudioProvider, GameAudioToggle, GameCanvas2D, GameHud, GameMenu, GameOverScreen, GameShell, GameTemplate, GenericAppTemplate, GeometricPattern, GradientDivider, GraphCanvas, GraphView, Grid, HStack, Header, Heading, HealthBar, HealthPanel, HeroOrganism, HeroSection, I18nProvider, IDENTITY_BOOK_FIELDS, Icon, InfiniteScrollSentinel, Input, InputGroup, InstallBox, InventoryGrid, InventoryPanel, IsometricCanvas, ItemSlot, JazariStateMachine, Label, LandingPageTemplate, LawReferenceTooltip, Lightbox, LikertScale, LineChart2 as LineChart, List3 as List, LoadingState, MapView, MarkdownContent, MarketingFooter, MarketingStatCard, MasterDetail, MasterDetailLayout, MatrixQuestion, MediaGallery, Menu, Meter, MiniMap, Modal, ModalSlot, ModuleCard, Navigation, NegotiatorBoard, NotifyListener, NumberStepper, ObjectRulePanel, OptionConstraintGroup, StateMachineView as OrbitalStateMachineView, OrbitalVisualization, Overlay, PageHeader, Pagination, PatternTile, PhysicsManager, PlatformerCanvas, Popover, PositionedCanvas, PowerupSlots, PricingCard, PricingGrid, PricingOrganism, PricingPageTemplate, ProgressBar, ProgressDots, PullQuote, PullToRefresh, QrScanner, QuestTracker, QuizBlock, Radio, RangeSlider, RelationSelect, RepeatableFormSection, ReplyTree, ResourceBar, ResourceCounter, RichBlockEditor, RuleEditor, RuntimeDebugger, SHEET_COLUMNS, SPRITE_SHEET_LAYOUT, ScaledDiagram, ScoreBoard, ScoreDisplay, SearchInput, Section, SectionHeader, Select, SequenceBar, SequencerBoard, ServiceCatalog, ShowcaseCard, ShowcaseOrganism, SidePanel, Sidebar, SignaturePad, SimpleGrid, SimulationCanvas, SimulationControls, SimulationGraph, SimulatorBoard, Skeleton, SlotContentRenderer, SocialProof, SortableList, Spacer, Sparkline, Spinner, Split, SplitPane, SplitSection, Sprite, Stack, StarRating, StatBadge, StatCard, StatDisplay, StateArchitectBoard, StateIndicator, StateMachineView, StateNode2 as StateNode, StatsGrid, StatsOrganism, StatusBar, StatusDot, StatusEffect, StepFlow, StepFlowOrganism, SvgBranch, SvgConnection, SvgFlow, SvgGrid, SvgLobe, SvgMesh, SvgMorph, SvgNode, SvgPulse, SvgRing, SvgShield, SvgStack, SwipeableRow, Switch, TERRAIN_COLORS, TILE_HEIGHT, TILE_WIDTH, TabbedContainer, Table, TableView, Tabs, TagCloud, TagInput, TeamCard, TeamOrganism, TerrainPalette, Text, TextHighlight, Textarea, ThemeSelector, ThemeToggle, TimeSlotCell, Timeline, TimerDisplay, Toast, ToastSlot, Tooltip, TraitFrame, TraitSlot, TraitStateViewer, TransitionArrow, TrendIndicator, TurnIndicator, TurnPanel, TypewriterText, Typography, UISlotComponent, UISlotRenderer, UncontrolledBattleBoard, UnitCommandBar, UploadDropZone, VStack, VariablePanel, VersionDiff, ViolationAlert, VoteStack, WaypointMarker, WizardContainer, WizardNavigation, WizardProgress, WorldMapBoard, WorldMapTemplate, XPBar, applyTemporaryEffect, calculateAttackTargets, calculateDamage, calculateValidMoves, clearEntities, cn, combatAnimations, combatClasses, combatEffects, createInitialGameState, createTranslate, createUnitAnimationState, drawSprite, generateCombatMessage, getAllEntities, getByType, getCurrentFrame, getEntity, getSingleton, getTileDimensions, inferDirection, isoToScreen, mapBookData, parseQueryBinding, pendulum, projectileMotion, removeEntity, resolveFieldMap, resolveFrame, resolveSheetDirection, screenToIso, spawnEntity, springOscillator, tickAnimationState, transitionAnimation, updateEntity, updateSingleton, useAgentChat, useAuthContext, useBattleState, useCamera, useCompile, useConnectGitHub, useDeepAgentGeneration, useDisconnectGitHub, useDragReorder, useDraggable, useDropZone, useEmitEvent, useEntities, useEntitiesByType, useEntity as useEntityById, useEventBus, useEventListener, useExtensions, useFileEditor, useFileSystem, useGameAudio, useGameAudioContext, useGitHubBranches, useGitHubRepo, useGitHubRepos, useGitHubStatus, useImageCache, useInfiniteScroll, useInput, useLongPress, useOrbitalHistory, usePhysics, usePhysics2D, usePinchZoom, usePlayer, usePreview, usePullToRefresh, useQuerySingleton, useSingletonEntity, useSpriteAnimations, useSwipeGesture, useTraitListens, useTranslate, useUIEvents, useUISlotManager, useValidation };
@@ -0,0 +1,105 @@
1
+ /**
2
+ * TableView Molecule
3
+ *
4
+ * A simplified, schema-driven column table for iterating over entity data.
5
+ * The table-shaped sibling of DataList (rows) and DataGrid (cards): same
6
+ * `entity` + `columns`/`fields` + `itemActions` contract and the same
7
+ * `useDataDnd` drag-to-reorder machinery, rendered as aligned columns with a
8
+ * header. All complexity is opt-in: selection, drag-reorder, and per-column
9
+ * sorting are each enabled by their own props and emit via the event bus.
10
+ *
11
+ * Uses atoms only internally: Box, VStack, HStack, Typography, Badge, Button,
12
+ * Icon, Checkbox, Divider.
13
+ */
14
+ import React from 'react';
15
+ import type { EntityRow, EventKey } from '@almadar/core';
16
+ import { type DataDndProps } from './useDataDnd';
17
+ export interface TableViewColumn {
18
+ /** Stable column key (React key + default value lookup). */
19
+ key: string;
20
+ /** Entity field to read (dot-notation ok). Defaults to `key`. */
21
+ field?: string;
22
+ /** Header cell text. Falls back to `label`, then a humanized `key`. */
23
+ header?: string;
24
+ /** Accessibility / fallback label. */
25
+ label?: string;
26
+ /** Width utility class applied to header + body cells (e.g. "w-28", "flex-1", "min-w-[10rem]"). */
27
+ width?: string;
28
+ /** Horizontal alignment of the column's cells. */
29
+ align?: 'left' | 'center' | 'right';
30
+ /** Extra cell classes (e.g. "font-mono tabular-nums truncate"). */
31
+ className?: string;
32
+ /** Render the cell value with the given font weight. */
33
+ weight?: 'normal' | 'medium' | 'semibold';
34
+ /** Value formatting hint. `badge` renders a status Badge. */
35
+ format?: 'badge' | 'date' | 'currency' | 'number' | 'percent' | 'boolean';
36
+ /** Lucide icon shown before the header label. */
37
+ icon?: string;
38
+ /** Allow click-to-sort on this column's header (emits `sortEvent`). */
39
+ sortable?: boolean;
40
+ }
41
+ export interface TableViewItemAction {
42
+ /** Button label. */
43
+ label: string;
44
+ /** Event name to emit (dispatched as UI:{event} with { id, row }). */
45
+ event: EventKey;
46
+ /** Lucide icon name. */
47
+ icon?: string;
48
+ /** Button variant. */
49
+ variant?: 'primary' | 'secondary' | 'ghost' | 'danger';
50
+ }
51
+ export interface TableViewProps<T extends EntityRow = EntityRow> extends DataDndProps {
52
+ /** Schema entity data — single record or collection. */
53
+ entity: T | readonly T[];
54
+ /** Column definitions. The compiler emits `columns`; `fields` is the alias. */
55
+ columns?: readonly TableViewColumn[];
56
+ /** Alias for `columns`. */
57
+ fields?: readonly TableViewColumn[];
58
+ /** Per-row action buttons (trailing column). */
59
+ itemActions?: readonly TableViewItemAction[];
60
+ /** Render a leading checkbox column. Selection changes emit `selectEvent`. */
61
+ selectable?: boolean;
62
+ /** Event emitted on selection change: UI:{selectEvent} with { ids, rows }. */
63
+ selectEvent?: EventKey;
64
+ /** Currently-selected ids (controlled). Falls back to local state when omitted. */
65
+ selectedIds?: readonly string[];
66
+ /** Event emitted on sortable-header click: UI:{sortEvent} with { column, direction }. */
67
+ sortEvent?: EventKey;
68
+ /** Current sort column (display hint for the active header arrow). */
69
+ sortColumn?: string;
70
+ /** Current sort direction (display hint). */
71
+ sortDirection?: 'asc' | 'desc';
72
+ /** Additional CSS classes applied to the table root. */
73
+ className?: string;
74
+ /** Message shown when there are no rows. */
75
+ emptyMessage?: string;
76
+ /** Loading state. */
77
+ isLoading?: boolean;
78
+ /** Error state. */
79
+ error?: Error | null;
80
+ /** Group rows under section headers by a field value. */
81
+ groupBy?: string;
82
+ /** Max rows before a "Show More" button. Defaults to 0 (show all). */
83
+ pageSize?: number;
84
+ /**
85
+ * Custom per-row render. When provided, the whole row content is delegated
86
+ * to this function (columns are ignored for the body; the header still
87
+ * renders). Mirrors DataList's children render prop.
88
+ */
89
+ children?: (item: T, index: number) => React.ReactNode;
90
+ /**
91
+ * Per-row render function (schema alias). In .orb: ["fn","item",{...}].
92
+ * The compiler converts this to the children render prop.
93
+ * @deprecated Use children in React code; exists for pattern registry sync.
94
+ */
95
+ renderItem?: (item: T, index: number) => React.ReactNode;
96
+ /**
97
+ * Layer 2 visual treatment — mirrors the data-list / entity-table look enum
98
+ * so authors share one knob name across row renderers.
99
+ */
100
+ look?: 'dense' | 'spacious' | 'striped' | 'borderless' | 'bordered';
101
+ }
102
+ export declare function TableView<T extends EntityRow = EntityRow>({ entity, columns, fields, itemActions, selectable, selectEvent, selectedIds, sortEvent, sortColumn, sortDirection, className, emptyMessage, isLoading, error, groupBy, pageSize, children, renderItem: _schemaRenderItem, look, dragGroup, accepts, sortable, dropEvent, reorderEvent, positionEvent, dndItemIdField, dndRoot, }: TableViewProps<T>): import("react/jsx-runtime").JSX.Element;
103
+ export declare namespace TableView {
104
+ var displayName: string;
105
+ }
@@ -53,6 +53,7 @@ export { UploadDropZone, type UploadDropZoneProps } from './UploadDropZone';
53
53
  export { Lightbox, type LightboxProps, type LightboxImage } from './Lightbox';
54
54
  export { DataGrid, type DataGridProps, type DataGridField, type DataGridItemAction } from './DataGrid';
55
55
  export { DataList, type DataListProps, type DataListField, type DataListItemAction } from './DataList';
56
+ export { TableView, type TableViewProps, type TableViewColumn } from './TableView';
56
57
  export { StatDisplay, type StatDisplayProps } from './StatDisplay';
57
58
  export { Meter, type MeterProps, type MeterVariant, type MeterThreshold, type MeterAction } from './Meter';
58
59
  export { SwipeableRow, type SwipeableRowProps, type SwipeAction } from './SwipeableRow';
@@ -16,6 +16,8 @@ type BoxBg = "transparent" | "primary" | "secondary" | "muted" | "accent" | "sur
16
16
  type BoxRounded = "none" | "sm" | "md" | "lg" | "xl" | "2xl" | "full";
17
17
  type BoxShadow = "none" | "sm" | "md" | "lg" | "xl";
18
18
  interface BoxProps extends React.HTMLAttributes<HTMLDivElement> {
19
+ /** Additional CSS classes applied to the root element. */
20
+ className?: string;
19
21
  /** Padding on all sides */
20
22
  padding?: BoxPadding;
21
23
  /** Horizontal padding (overrides padding for x-axis) */
@@ -169,6 +171,8 @@ declare const Typography: React.FC<TypographyProps>;
169
171
  type ButtonVariant = "primary" | "secondary" | "ghost" | "danger" | "success" | "warning" | "default";
170
172
  type ButtonSize = "sm" | "md" | "lg";
171
173
  interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
174
+ /** Additional CSS classes applied to the root element. */
175
+ className?: string;
172
176
  variant?: ButtonVariant;
173
177
  size?: ButtonSize;
174
178
  isLoading?: boolean;
@@ -234,6 +238,8 @@ type CardShadow = "none" | "sm" | "md" | "lg";
234
238
  */
235
239
  type CardLook = "elevated" | "flat-bordered" | "borderless-divider" | "ticket" | "invoice" | "chip" | "tile-image-first";
236
240
  interface CardProps extends React.HTMLAttributes<HTMLDivElement> {
241
+ /** Additional CSS classes applied to the root element. */
242
+ className?: string;
237
243
  variant?: "default" | "bordered" | "elevated" | "interactive";
238
244
  padding?: "none" | "sm" | "md" | "lg";
239
245
  /** Card title - renders in header if provided */
@@ -284,6 +290,8 @@ interface SelectOption {
284
290
  label: string;
285
291
  }
286
292
  interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "onChange"> {
293
+ /** Additional CSS classes applied to the root element. */
294
+ className?: string;
287
295
  /** Placeholder text */
288
296
  placeholder?: string;
289
297
  /** Current value */
@@ -15,6 +15,8 @@ type BoxBg = "transparent" | "primary" | "secondary" | "muted" | "accent" | "sur
15
15
  type BoxRounded = "none" | "sm" | "md" | "lg" | "xl" | "2xl" | "full";
16
16
  type BoxShadow = "none" | "sm" | "md" | "lg" | "xl";
17
17
  interface BoxProps extends React.HTMLAttributes<HTMLDivElement> {
18
+ /** Additional CSS classes applied to the root element. */
19
+ className?: string;
18
20
  /** Padding on all sides */
19
21
  padding?: BoxPadding;
20
22
  /** Horizontal padding (overrides padding for x-axis) */
@@ -168,6 +170,8 @@ declare const Typography: React.FC<TypographyProps>;
168
170
  type ButtonVariant = "primary" | "secondary" | "ghost" | "danger" | "success" | "warning" | "default";
169
171
  type ButtonSize = "sm" | "md" | "lg";
170
172
  interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
173
+ /** Additional CSS classes applied to the root element. */
174
+ className?: string;
171
175
  variant?: ButtonVariant;
172
176
  size?: ButtonSize;
173
177
  isLoading?: boolean;
@@ -193,6 +197,8 @@ declare const Button: React.ForwardRefExoticComponent<ButtonProps & React.RefAtt
193
197
  type BadgeVariant = "default" | "primary" | "secondary" | "success" | "warning" | "danger" | "error" | "info" | "neutral";
194
198
  type BadgeSize = "sm" | "md" | "lg";
195
199
  interface BadgeProps extends React.HTMLAttributes<HTMLSpanElement> {
200
+ /** Additional CSS classes applied to the root element. */
201
+ className?: string;
196
202
  variant?: BadgeVariant;
197
203
  size?: BadgeSize;
198
204
  /** Numeric count or amount to display in badge */
@@ -256,6 +262,8 @@ type CardShadow = "none" | "sm" | "md" | "lg";
256
262
  */
257
263
  type CardLook = "elevated" | "flat-bordered" | "borderless-divider" | "ticket" | "invoice" | "chip" | "tile-image-first";
258
264
  interface CardProps extends React.HTMLAttributes<HTMLDivElement> {
265
+ /** Additional CSS classes applied to the root element. */
266
+ className?: string;
259
267
  variant?: "default" | "bordered" | "elevated" | "interactive";
260
268
  padding?: "none" | "sm" | "md" | "lg";
261
269
  /** Card title - renders in header if provided */
@@ -859,6 +867,8 @@ declare const AnimatedCounter: React.FC<AnimatedCounterProps>;
859
867
  type RevealTrigger = 'scroll' | 'hover' | 'manual';
860
868
  type RevealAnimation = 'fade-up' | 'fade-down' | 'fade-in' | 'fade-left' | 'fade-right' | 'scale' | 'scale-up' | 'none';
861
869
  interface AnimatedRevealProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {
870
+ /** Additional CSS classes applied to the root element. */
871
+ className?: string;
862
872
  /** What triggers the animation */
863
873
  trigger?: RevealTrigger;
864
874
  /** Built-in animation preset */
@@ -882,6 +892,8 @@ declare const AnimatedReveal: React.ForwardRefExoticComponent<AnimatedRevealProp
882
892
 
883
893
  type GraphicAnimation = 'draw' | 'fill' | 'pulse' | 'morph';
884
894
  interface AnimatedGraphicProps extends React.HTMLAttributes<HTMLDivElement> {
895
+ /** Additional CSS classes applied to the root element. */
896
+ className?: string;
885
897
  /** URL to an SVG file. Fetched and inlined to enable stroke/fill animations. */
886
898
  src?: string;
887
899
  /** Inline SVG string. Takes precedence over src if both provided. */