@c2n/mcp 0.0.10 → 0.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/data/registry.json +864 -16
  2. package/package.json +2 -2
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "c2nVersion": "0.0.10",
3
+ "c2nVersion": "0.0.12",
4
4
  "categories": [
5
5
  "Inputs",
6
6
  "Buttons",
@@ -11664,7 +11664,7 @@
11664
11664
  "default": "420px",
11665
11665
  "part": "",
11666
11666
  "property": "max-height",
11667
- "description": "The editor scrolls past this height."
11667
+ "description": "The editor scrolls past this height. A height set on the element itself reaches the editor (the label and supporting text keep theirs); set this to `none` to fill it."
11668
11668
  },
11669
11669
  {
11670
11670
  "name": "--c2-code-editor--padding-block",
@@ -14062,6 +14062,832 @@
14062
14062
  ],
14063
14063
  "hasGallery": true
14064
14064
  },
14065
+ "dashboard": {
14066
+ "id": "dashboard",
14067
+ "package": "@c2n/dashboard",
14068
+ "title": "Dashboard",
14069
+ "description": "Grid of resizable panes, dragged by the edges they share.",
14070
+ "intro": "`c2-dashboard` is a CSS grid whose tracks the user can drag. Its children are `c2-dash-card` panes, each placed by",
14071
+ "category": "Layout",
14072
+ "status": "stable",
14073
+ "docsUrl": "https://code2nguyen.github.io/web-components/components/dashboard",
14074
+ "elements": [
14075
+ {
14076
+ "tag": "c2-dashboard",
14077
+ "className": "Dashboard",
14078
+ "modulePath": "@c2n/dashboard",
14079
+ "description": "Grid of resizable panes. The children are `c2-dash-card` elements, placed by their `col`/`row` attributes; each\none draws drag handles on the edges it shares with a neighbour, and dragging one resizes the whole track, so the\ncards on either side stay aligned. `columns` and `rows` take a track count (`columns=\"3\"` is three equal columns)\nor an explicit track list (`columns=\"320px 1fr\"`); a track is switched to pixels the first time it is dragged, and\nthe `fr` tracks around it give up the space in proportion to their weight, down to the minimums. With a\n`storage-key` the sizes survive a reload.\n\n`layouts` makes the grid responsive without a remount: each entry names a media query and the tracks and card\nplacements to use while it matches, the first match wins, and every entry keeps its own stored sizes under\n`<storage-key>@<media>`.\n\nPlacement is the application's: the grid never re-places cards on its own. A pane removed or hidden at runtime\nleaves its cells empty and its neighbours where they were, and a pane added at runtime lands exactly where its\n`col`/`row` say, on top of whatever is already there if that cell is taken. To close a gap, or to make room, set\nthe cards' `col`/`row`/`col-span`/`row-span` or hand the grid a `layout` record — both are applied in place.\n\nThe grid is the sizing authority: a card never sets its own width. Give the element a height (or place it in a\nflex/grid parent that does) whenever the rows use `fr`, since the row tracks divide the host's height.",
14080
+ "attributes": [
14081
+ {
14082
+ "name": "columns",
14083
+ "type": "number | string | string[]",
14084
+ "default": "2",
14085
+ "description": "Column count (`3`) or an explicit track list (`'320px 1fr'`). Each entry must be one simple size."
14086
+ },
14087
+ {
14088
+ "name": "rows",
14089
+ "type": "number | string | string[]",
14090
+ "default": "1",
14091
+ "description": "Row count (`2`) or an explicit track list (`'auto 1fr'`)."
14092
+ },
14093
+ {
14094
+ "name": "min-column-width",
14095
+ "type": "number",
14096
+ "default": "50",
14097
+ "description": "Floor for every column, in pixels. A card's own `min-width` raises it for the tracks that card covers."
14098
+ },
14099
+ {
14100
+ "name": "min-row-height",
14101
+ "type": "number",
14102
+ "default": "50",
14103
+ "description": "Floor for every row, in pixels. A card's own `min-height` raises it for the tracks that card covers."
14104
+ },
14105
+ {
14106
+ "name": "storage-key",
14107
+ "type": "string | undefined",
14108
+ "default": "undefined",
14109
+ "description": "`localStorage` key the track sizes are stored under. Without it the grid starts from the authored tracks."
14110
+ }
14111
+ ],
14112
+ "slots": [
14113
+ {
14114
+ "name": "",
14115
+ "description": "The `c2-dash-card` panes. Anything else becomes an ordinary grid item, placed by your own CSS."
14116
+ }
14117
+ ],
14118
+ "events": [
14119
+ {
14120
+ "name": "layout-change",
14121
+ "type": "CustomEvent<DashboardLayoutChangeDetail>",
14122
+ "description": "The track sizes changed: a gesture ended, `reset()` was called, or another entry of `layouts` took over. Does not bubble: listen on the element."
14123
+ }
14124
+ ],
14125
+ "cssParts": [],
14126
+ "cssProperties": [
14127
+ {
14128
+ "name": "--c2-dashboard--gap",
14129
+ "type": "pixel",
14130
+ "default": "8px",
14131
+ "part": "",
14132
+ "property": "gap",
14133
+ "description": "Gutter between the cards. The whole gutter drags: each card's handle is centred on its edge and as thick as the gap (never under `--c2-dash-card__handle--size`)."
14134
+ },
14135
+ {
14136
+ "name": "--c2-dashboard--padding",
14137
+ "type": "padding",
14138
+ "default": "0px",
14139
+ "part": "",
14140
+ "property": "padding",
14141
+ "description": "Inset around the tracks. With a `background` it is what turns the gutters into a visible frame between the panes."
14142
+ },
14143
+ {
14144
+ "name": "--c2-dashboard--background",
14145
+ "type": "background",
14146
+ "default": "transparent",
14147
+ "part": "",
14148
+ "property": "background"
14149
+ },
14150
+ {
14151
+ "name": "--c2-dashboard--border",
14152
+ "type": "border",
14153
+ "default": "none",
14154
+ "part": "",
14155
+ "property": "border"
14156
+ },
14157
+ {
14158
+ "name": "--c2-dashboard--border-radius",
14159
+ "type": "border-radius",
14160
+ "default": "0px",
14161
+ "part": "",
14162
+ "property": "border-radius"
14163
+ }
14164
+ ]
14165
+ },
14166
+ {
14167
+ "tag": "c2-dash-card",
14168
+ "className": "DashCard",
14169
+ "modulePath": "@c2n/dashboard/dash-card.js",
14170
+ "description": "One pane of a `c2-dashboard`. It owns its place in the grid (`col`, `row`, `col-span`, `row-span`), the drag\nhandles on the edges it shares with a neighbour, and the optional expand controls; it draws no surface of its\nown, so put a `c2-card` — or any markup — in the default slot.\n\nA handle resizes the whole grid track, never just this card, and it only appears where there is a neighbour to\ntake the space from: the right edge has one when another column follows, the left edge when one precedes. Drag\nit, or focus it and use the arrow keys (10px a step, 1px with Shift).\n\nFilling the `header`, `actions` or `footer` slot turns on that row; with the header and actions both empty the\nexpand controls float over the top-right corner of the pane instead. An expanded card covers its neighbours on\nan opaque `--c2-dash-card__expanded--background` (the theme's surface colour), while the card itself stays\ntransparent at rest.\n\nA card that arrives while the grid is already on screen fades and scales in; one that leaves — through the\ngrid's `layout` record (`visible: false`) or through `dismiss()`, which removes the element once the animation\nhas played — fades out the same way. Cards present at load do not animate, and `prefers-reduced-motion` turns\nboth off.\n\nEvery built-in icon is a slot whose fallback is the default drawing, so a pane can use the host application's own\nicon set without giving up the behaviour.",
14171
+ "attributes": [
14172
+ {
14173
+ "name": "card-id",
14174
+ "type": "string | undefined",
14175
+ "default": "undefined",
14176
+ "description": "Identifier the grid's `layout` record is keyed by."
14177
+ },
14178
+ {
14179
+ "name": "col",
14180
+ "type": "number",
14181
+ "default": "1",
14182
+ "description": "1-based column the card starts in."
14183
+ },
14184
+ {
14185
+ "name": "row",
14186
+ "type": "number",
14187
+ "default": "1",
14188
+ "description": "1-based row the card starts in."
14189
+ },
14190
+ {
14191
+ "name": "col-span",
14192
+ "type": "number",
14193
+ "default": "1",
14194
+ "description": "Number of columns the card occupies."
14195
+ },
14196
+ {
14197
+ "name": "row-span",
14198
+ "type": "number",
14199
+ "default": "1",
14200
+ "description": "Number of rows the card occupies."
14201
+ },
14202
+ {
14203
+ "name": "min-width",
14204
+ "type": "number",
14205
+ "default": "0",
14206
+ "description": "Smallest width in pixels the card accepts; it raises the minimum of every column it covers."
14207
+ },
14208
+ {
14209
+ "name": "min-height",
14210
+ "type": "number",
14211
+ "default": "0",
14212
+ "description": "Smallest height in pixels the card accepts; it raises the minimum of every row it covers."
14213
+ },
14214
+ {
14215
+ "name": "resize",
14216
+ "type": "DashCardResize",
14217
+ "default": "'both'",
14218
+ "description": "Which edges carry a drag handle."
14219
+ },
14220
+ {
14221
+ "name": "expand-width",
14222
+ "type": "boolean",
14223
+ "default": "false",
14224
+ "description": "Offers a control that expands the card across every column."
14225
+ },
14226
+ {
14227
+ "name": "expand-height",
14228
+ "type": "boolean",
14229
+ "default": "false",
14230
+ "description": "Offers a control that expands the card across every row."
14231
+ },
14232
+ {
14233
+ "name": "expand-full",
14234
+ "type": "boolean",
14235
+ "default": "false",
14236
+ "description": "Offers a control that expands the card over the whole grid."
14237
+ },
14238
+ {
14239
+ "name": "expanded",
14240
+ "type": "DashCardExpanded",
14241
+ "default": "'none'",
14242
+ "description": "How far the card is currently expanded. Settable, so an app can expand a card from its own control."
14243
+ }
14244
+ ],
14245
+ "slots": [
14246
+ {
14247
+ "name": "",
14248
+ "description": "Pane content. It fills the pane: the body is a column flex box and every slotted child is a `flex: 1` item with `min-height: 0`, so a chart or an editor follows the row track without a `height: 100%` chain."
14249
+ },
14250
+ {
14251
+ "name": "header",
14252
+ "description": "Title area of the header row; filling it turns the row on."
14253
+ },
14254
+ {
14255
+ "name": "actions",
14256
+ "description": "Your own controls at the end of the header row, before the built-in expand buttons and separated from them by `--c2-dash-card__actions--gap`."
14257
+ },
14258
+ {
14259
+ "name": "controls",
14260
+ "description": "Your own controls inside the built-in group, immediately before the expand buttons — for a button that belongs with them, such as a refresh or a close."
14261
+ },
14262
+ {
14263
+ "name": "footer",
14264
+ "description": "Status bar under the pane content; filling it turns the row on."
14265
+ },
14266
+ {
14267
+ "name": "expand-width-icon",
14268
+ "description": "Icon of the full-width control while the card is not expanded that way."
14269
+ },
14270
+ {
14271
+ "name": "collapse-width-icon",
14272
+ "description": "Icon of the full-width control while it is."
14273
+ },
14274
+ {
14275
+ "name": "expand-height-icon",
14276
+ "description": "Icon of the full-height control while the card is not expanded that way."
14277
+ },
14278
+ {
14279
+ "name": "collapse-height-icon",
14280
+ "description": "Icon of the full-height control while it is."
14281
+ },
14282
+ {
14283
+ "name": "expand-full-icon",
14284
+ "description": "Icon of the fullscreen control while the card is not expanded."
14285
+ },
14286
+ {
14287
+ "name": "collapse-full-icon",
14288
+ "description": "Icon of the fullscreen control while it is."
14289
+ }
14290
+ ],
14291
+ "events": [
14292
+ {
14293
+ "name": "expand-change",
14294
+ "type": "CustomEvent<DashCardExpandChangeDetail>",
14295
+ "description": "The card was expanded or collapsed through one of its own controls. Does not bubble: listen on the element."
14296
+ }
14297
+ ],
14298
+ "cssParts": [
14299
+ {
14300
+ "name": "header",
14301
+ "description": "The header row, or the floating control group when the header and actions slots are empty."
14302
+ },
14303
+ {
14304
+ "name": "body",
14305
+ "description": "The wrapper around the default slot."
14306
+ },
14307
+ {
14308
+ "name": "footer",
14309
+ "description": "The footer row."
14310
+ },
14311
+ {
14312
+ "name": "controls",
14313
+ "description": "The group holding the `controls` slot and the built-in expand buttons."
14314
+ },
14315
+ {
14316
+ "name": "control",
14317
+ "description": "One built-in expand button."
14318
+ },
14319
+ {
14320
+ "name": "handle",
14321
+ "description": "Every drag handle. Each also carries the part of its edge."
14322
+ },
14323
+ {
14324
+ "name": "handle-left",
14325
+ "description": "The handle on the left edge."
14326
+ },
14327
+ {
14328
+ "name": "handle-right",
14329
+ "description": "The handle on the right edge."
14330
+ },
14331
+ {
14332
+ "name": "handle-top",
14333
+ "description": "The handle on the top edge."
14334
+ },
14335
+ {
14336
+ "name": "handle-bottom",
14337
+ "description": "The handle on the bottom edge."
14338
+ }
14339
+ ],
14340
+ "cssProperties": [
14341
+ {
14342
+ "name": "--c2-dash-card--background",
14343
+ "type": "background",
14344
+ "default": "transparent",
14345
+ "part": "",
14346
+ "property": "background"
14347
+ },
14348
+ {
14349
+ "name": "--c2-dash-card--border",
14350
+ "type": "border",
14351
+ "default": "none",
14352
+ "part": "",
14353
+ "property": "border"
14354
+ },
14355
+ {
14356
+ "name": "--c2-dash-card--border-radius",
14357
+ "type": "border-radius",
14358
+ "default": "0px",
14359
+ "part": "",
14360
+ "property": "border-radius"
14361
+ },
14362
+ {
14363
+ "name": "--c2-dash-card--box-shadow",
14364
+ "type": "box-shadow",
14365
+ "default": "none",
14366
+ "part": "",
14367
+ "property": "box-shadow"
14368
+ },
14369
+ {
14370
+ "name": "--c2-dash-card--padding",
14371
+ "type": "padding",
14372
+ "default": "0px",
14373
+ "part": "",
14374
+ "property": "padding"
14375
+ },
14376
+ {
14377
+ "name": "--c2-dash-card--overflow",
14378
+ "type": "overflow",
14379
+ "default": "hidden",
14380
+ "part": "",
14381
+ "property": "overflow",
14382
+ "description": "`hidden` keeps the content inside the track; switch it to `visible` for a pane that has to overflow, such as one holding a menu."
14383
+ },
14384
+ {
14385
+ "name": "--c2-dash-card__expanded--background",
14386
+ "type": "background",
14387
+ "default": "#ffffff",
14388
+ "part": "",
14389
+ "state": "expanded",
14390
+ "property": "background",
14391
+ "token": "--c2-theme--color-surface",
14392
+ "description": "Fill while the card is expanded over its neighbours, so they do not show through; the card's own `background` stays transparent."
14393
+ },
14394
+ {
14395
+ "name": "--c2-dash-card__expanded--z-index",
14396
+ "type": "number",
14397
+ "default": "20",
14398
+ "part": "",
14399
+ "state": "expanded",
14400
+ "property": "z-index"
14401
+ },
14402
+ {
14403
+ "name": "--c2-dash-card__enter--animation-duration",
14404
+ "type": "duration",
14405
+ "default": "200ms",
14406
+ "part": "enter",
14407
+ "property": "animation-duration",
14408
+ "token": "--c2-theme--motion-scale",
14409
+ "description": "Fade and scale-in of a card added to a grid that is already on screen, or shown again through the layout record. `0ms` disables it."
14410
+ },
14411
+ {
14412
+ "name": "--c2-dash-card__leave--animation-duration",
14413
+ "type": "duration",
14414
+ "default": "160ms",
14415
+ "part": "leave",
14416
+ "property": "animation-duration",
14417
+ "token": "--c2-theme--motion-scale",
14418
+ "description": "Fade-out before a card is hidden by the layout record or removed by `dismiss()`. `0ms` disables it."
14419
+ },
14420
+ {
14421
+ "name": "--c2-dash-card__expanded--animation-duration",
14422
+ "type": "duration",
14423
+ "default": "200ms",
14424
+ "part": "",
14425
+ "state": "expanded",
14426
+ "property": "animation-duration",
14427
+ "token": "--c2-theme--motion-scale",
14428
+ "description": "Length of the scale-in the card plays when it expands or collapses. Ignored under `prefers-reduced-motion`."
14429
+ },
14430
+ {
14431
+ "name": "--c2-dash-card__header--min-height",
14432
+ "type": "pixel",
14433
+ "default": "44px",
14434
+ "part": "header",
14435
+ "property": "min-height"
14436
+ },
14437
+ {
14438
+ "name": "--c2-dash-card__header--padding-block",
14439
+ "type": "padding",
14440
+ "default": "8px",
14441
+ "part": "header",
14442
+ "property": "padding-block"
14443
+ },
14444
+ {
14445
+ "name": "--c2-dash-card__header--padding-inline",
14446
+ "type": "padding",
14447
+ "default": "12px",
14448
+ "part": "header",
14449
+ "property": "padding-inline"
14450
+ },
14451
+ {
14452
+ "name": "--c2-dash-card__header--gap",
14453
+ "type": "pixel",
14454
+ "default": "12px",
14455
+ "part": "header",
14456
+ "property": "gap"
14457
+ },
14458
+ {
14459
+ "name": "--c2-dash-card__header--background",
14460
+ "type": "background",
14461
+ "default": "transparent",
14462
+ "part": "header",
14463
+ "property": "background"
14464
+ },
14465
+ {
14466
+ "name": "--c2-dash-card__header--border-bottom",
14467
+ "type": "border",
14468
+ "default": "none",
14469
+ "part": "header",
14470
+ "property": "border-bottom"
14471
+ },
14472
+ {
14473
+ "name": "--c2-dash-card__header--color",
14474
+ "type": "color",
14475
+ "default": "#18181b",
14476
+ "part": "header",
14477
+ "property": "color",
14478
+ "token": "--c2-theme--color-on-surface"
14479
+ },
14480
+ {
14481
+ "name": "--c2-dash-card__header--font-size",
14482
+ "type": "pixel",
14483
+ "default": "14px",
14484
+ "part": "header",
14485
+ "property": "font-size",
14486
+ "token": "--c2-theme--font-size-md"
14487
+ },
14488
+ {
14489
+ "name": "--c2-dash-card__header--font-weight",
14490
+ "type": "font-weight",
14491
+ "default": "600",
14492
+ "part": "header",
14493
+ "property": "font-weight",
14494
+ "token": "--c2-theme--font-weight-semibold"
14495
+ },
14496
+ {
14497
+ "name": "--c2-dash-card__footer--min-height",
14498
+ "type": "pixel",
14499
+ "default": "36px",
14500
+ "part": "footer",
14501
+ "property": "min-height"
14502
+ },
14503
+ {
14504
+ "name": "--c2-dash-card__footer--padding-block",
14505
+ "type": "padding",
14506
+ "default": "6px",
14507
+ "part": "footer",
14508
+ "property": "padding-block"
14509
+ },
14510
+ {
14511
+ "name": "--c2-dash-card__footer--padding-inline",
14512
+ "type": "padding",
14513
+ "default": "12px",
14514
+ "part": "footer",
14515
+ "property": "padding-inline"
14516
+ },
14517
+ {
14518
+ "name": "--c2-dash-card__footer--gap",
14519
+ "type": "pixel",
14520
+ "default": "8px",
14521
+ "part": "footer",
14522
+ "property": "gap"
14523
+ },
14524
+ {
14525
+ "name": "--c2-dash-card__footer--background",
14526
+ "type": "background",
14527
+ "default": "transparent",
14528
+ "part": "footer",
14529
+ "property": "background"
14530
+ },
14531
+ {
14532
+ "name": "--c2-dash-card__footer--border-top",
14533
+ "type": "border",
14534
+ "default": "none",
14535
+ "part": "footer",
14536
+ "property": "border-top"
14537
+ },
14538
+ {
14539
+ "name": "--c2-dash-card__footer--color",
14540
+ "type": "color",
14541
+ "default": "#71717a",
14542
+ "part": "footer",
14543
+ "property": "color",
14544
+ "token": "--c2-theme--color-on-surface-variant"
14545
+ },
14546
+ {
14547
+ "name": "--c2-dash-card__footer--font-size",
14548
+ "type": "pixel",
14549
+ "default": "12px",
14550
+ "part": "footer",
14551
+ "property": "font-size",
14552
+ "token": "--c2-theme--font-size-sm"
14553
+ },
14554
+ {
14555
+ "name": "--c2-dash-card__actions--gap",
14556
+ "type": "pixel",
14557
+ "default": "8px",
14558
+ "part": "actions",
14559
+ "property": "gap"
14560
+ },
14561
+ {
14562
+ "name": "--c2-dash-card__controls--gap",
14563
+ "type": "pixel",
14564
+ "default": "2px",
14565
+ "part": "controls",
14566
+ "property": "gap"
14567
+ },
14568
+ {
14569
+ "name": "--c2-dash-card__controls--offset",
14570
+ "type": "pixel",
14571
+ "default": "4px",
14572
+ "part": "controls",
14573
+ "property": "offset",
14574
+ "description": "Inset of the floating control group from the top-right corner, used only while the header row is off."
14575
+ },
14576
+ {
14577
+ "name": "--c2-dash-card__control--size",
14578
+ "type": "pixel",
14579
+ "default": "24px",
14580
+ "part": "control",
14581
+ "property": "size"
14582
+ },
14583
+ {
14584
+ "name": "--c2-dash-card__control--icon-size",
14585
+ "type": "pixel",
14586
+ "default": "16px",
14587
+ "part": "control",
14588
+ "property": "icon-size"
14589
+ },
14590
+ {
14591
+ "name": "--c2-dash-card__control--border-radius",
14592
+ "type": "border-radius",
14593
+ "default": "6px",
14594
+ "part": "control",
14595
+ "property": "border-radius",
14596
+ "token": "--c2-theme--radius-md"
14597
+ },
14598
+ {
14599
+ "name": "--c2-dash-card__control--color",
14600
+ "type": "color",
14601
+ "default": "#71717a",
14602
+ "part": "control",
14603
+ "property": "color",
14604
+ "token": "--c2-theme--color-on-surface-variant"
14605
+ },
14606
+ {
14607
+ "name": "--c2-dash-card__control--background",
14608
+ "type": "background",
14609
+ "default": "transparent",
14610
+ "part": "control",
14611
+ "property": "background"
14612
+ },
14613
+ {
14614
+ "name": "--c2-dash-card__control__hover--background",
14615
+ "type": "background",
14616
+ "default": "#f4f4f5",
14617
+ "part": "control",
14618
+ "state": "hover",
14619
+ "property": "background",
14620
+ "token": "--c2-theme--color-surface-container"
14621
+ },
14622
+ {
14623
+ "name": "--c2-dash-card__control__hover--color",
14624
+ "type": "color",
14625
+ "default": "#18181b",
14626
+ "part": "control",
14627
+ "state": "hover",
14628
+ "property": "color",
14629
+ "token": "--c2-theme--color-on-surface"
14630
+ },
14631
+ {
14632
+ "name": "--c2-dash-card__control__focus--outline",
14633
+ "type": "outline",
14634
+ "default": "2px solid rgba(2, 101, 220, 0.4)",
14635
+ "part": "control",
14636
+ "state": "focus",
14637
+ "property": "outline",
14638
+ "token": "--c2-theme--focus-ring"
14639
+ },
14640
+ {
14641
+ "name": "--c2-dash-card__control__focus--outline-offset",
14642
+ "type": "pixel",
14643
+ "default": "2px",
14644
+ "part": "control",
14645
+ "state": "focus",
14646
+ "property": "outline-offset"
14647
+ },
14648
+ {
14649
+ "name": "--c2-dash-card__handle--size",
14650
+ "type": "pixel",
14651
+ "default": "6px",
14652
+ "part": "handle",
14653
+ "property": "size",
14654
+ "description": "Smallest thickness of the grab area on an edge. Inside a grid the handle is as thick as the gutter when that is wider, centred on the edge, so the whole gutter drags."
14655
+ },
14656
+ {
14657
+ "name": "--c2-dash-card__handle--inset",
14658
+ "type": "pixel",
14659
+ "default": "2px",
14660
+ "part": "handle",
14661
+ "property": "inset",
14662
+ "description": "Gap between the handle's visible bar and the ends of the edge."
14663
+ },
14664
+ {
14665
+ "name": "--c2-dash-card__handle--background",
14666
+ "type": "background",
14667
+ "default": "transparent",
14668
+ "part": "handle",
14669
+ "property": "background"
14670
+ },
14671
+ {
14672
+ "name": "--c2-dash-card__handle__hover--background",
14673
+ "type": "background",
14674
+ "default": "rgba(2, 101, 220, 0.2)",
14675
+ "part": "handle",
14676
+ "state": "hover",
14677
+ "property": "background",
14678
+ "token": "--c2-theme--color-primary-glow"
14679
+ },
14680
+ {
14681
+ "name": "--c2-dash-card__handle__active--background",
14682
+ "type": "background",
14683
+ "default": "rgb(2, 101, 220)",
14684
+ "part": "handle",
14685
+ "state": "active",
14686
+ "property": "background",
14687
+ "token": "--c2-theme--color-primary"
14688
+ },
14689
+ {
14690
+ "name": "--c2-dash-card__handle--border-radius",
14691
+ "type": "border-radius",
14692
+ "default": "999px",
14693
+ "part": "handle",
14694
+ "property": "border-radius",
14695
+ "token": "--c2-theme--radius-full"
14696
+ },
14697
+ {
14698
+ "name": "--c2-dash-card__handle--transition-duration",
14699
+ "type": "duration",
14700
+ "default": "150ms",
14701
+ "part": "handle",
14702
+ "property": "transition-duration",
14703
+ "token": "--c2-theme--motion-scale"
14704
+ },
14705
+ {
14706
+ "name": "--c2-dash-card__handle__focus--outline",
14707
+ "type": "outline",
14708
+ "default": "2px solid rgba(2, 101, 220, 0.4)",
14709
+ "part": "handle",
14710
+ "state": "focus",
14711
+ "property": "outline",
14712
+ "token": "--c2-theme--focus-ring"
14713
+ }
14714
+ ]
14715
+ }
14716
+ ],
14717
+ "composition": {
14718
+ "internal": [],
14719
+ "slotted": [],
14720
+ "usedBy": []
14721
+ },
14722
+ "install": {
14723
+ "npm": "npm install @c2n/dashboard @c2n/theme",
14724
+ "import": "import '@c2n/dashboard'",
14725
+ "importClass": "import { Dashboard } from '@c2n/dashboard'"
14726
+ },
14727
+ "presets": {
14728
+ "html": "<c2-dashboard style=\"height:200px\" columns=\"1fr 2fr\" rows=\"1fr 1fr\"><c2-dash-card col=\"1\" row=\"1\" row-span=\"2\"><span slot=\"header\">Watchlist</span></c2-dash-card><c2-dash-card col=\"2\" row=\"1\"><span slot=\"header\">Price</span></c2-dash-card><c2-dash-card col=\"2\" row=\"2\"><span slot=\"header\">Orders</span></c2-dash-card></c2-dashboard>",
14729
+ "items": [
14730
+ {
14731
+ "name": "Panes",
14732
+ "description": "A bordered white surface per pane, set off against a light canvas the gutters show through.",
14733
+ "css": {
14734
+ "--c2-dashboard--gap": "10px",
14735
+ "--c2-dashboard--padding": "10px",
14736
+ "--c2-dashboard--background": "#f1f2f4",
14737
+ "--c2-dashboard--border-radius": "12px",
14738
+ "--c2-dash-card--background": "#ffffff",
14739
+ "--c2-dash-card--border": "1px solid #e4e4e7",
14740
+ "--c2-dash-card--border-radius": "8px",
14741
+ "--c2-dash-card__expanded--background": "#ffffff",
14742
+ "--c2-dash-card__header--border-bottom": "1px solid #e4e4e7"
14743
+ }
14744
+ },
14745
+ {
14746
+ "name": "Seamless",
14747
+ "description": "No gutter to speak of: the grid background shows through as a hairline and the handle is what you aim at.",
14748
+ "css": {
14749
+ "--c2-dashboard--gap": "1px",
14750
+ "--c2-dashboard--padding": "1px",
14751
+ "--c2-dashboard--background": "#d4d4d8",
14752
+ "--c2-dashboard--border-radius": "10px",
14753
+ "--c2-dash-card--background": "#ffffff",
14754
+ "--c2-dash-card__expanded--background": "#ffffff",
14755
+ "--c2-dash-card__handle--size": "9px",
14756
+ "--c2-dash-card__handle__hover--background": "#0265dc"
14757
+ }
14758
+ },
14759
+ {
14760
+ "name": "Terminal",
14761
+ "description": "Dark panes, a compact monospace header row and a green handle under the pointer.",
14762
+ "css": {
14763
+ "--c2-dashboard--gap": "6px",
14764
+ "--c2-dashboard--padding": "6px",
14765
+ "--c2-dashboard--background": "#09090b",
14766
+ "--c2-dash-card--background": "#18181b",
14767
+ "--c2-dash-card--border": "1px solid #27272a",
14768
+ "--c2-dash-card--border-radius": "4px",
14769
+ "--c2-dash-card__expanded--background": "#18181b",
14770
+ "--c2-dash-card__header--color": "#a1a1aa",
14771
+ "--c2-dash-card__header--font-size": "12px",
14772
+ "--c2-dash-card__header--min-height": "28px",
14773
+ "--c2-dash-card__header--border-bottom": "1px solid #27272a",
14774
+ "--c2-dash-card__handle__hover--background": "#22c55e",
14775
+ "--c2-dash-card__handle__active--background": "#4ade80"
14776
+ }
14777
+ },
14778
+ {
14779
+ "name": "Soft",
14780
+ "description": "Floating cards: no border, a large radius and a shadow, over a generous gutter.",
14781
+ "css": {
14782
+ "--c2-dashboard--gap": "14px",
14783
+ "--c2-dashboard--padding": "14px",
14784
+ "--c2-dashboard--background": "#f1f2f4",
14785
+ "--c2-dashboard--border-radius": "18px",
14786
+ "--c2-dash-card--background": "#ffffff",
14787
+ "--c2-dash-card--border-radius": "14px",
14788
+ "--c2-dash-card--box-shadow": "0 1px 2px rgba(9, 9, 11, 0.06), 0 8px 24px rgba(9, 9, 11, 0.06)",
14789
+ "--c2-dash-card__expanded--background": "#ffffff",
14790
+ "--c2-dash-card__header--font-weight": "500",
14791
+ "--c2-dash-card__handle__hover--background": "rgba(9, 9, 11, 0.18)",
14792
+ "--c2-dash-card__handle__active--background": "rgba(9, 9, 11, 0.38)"
14793
+ }
14794
+ }
14795
+ ]
14796
+ },
14797
+ "examples": [
14798
+ {
14799
+ "kind": "usage",
14800
+ "label": "Three panes, drag any shared edge",
14801
+ "html": "<c2-dashboard client:only=\"lit\" class=\"demo-grid\" columns=\"320px 1fr\" rows=\"1fr 1fr\">\n <c2-dash-card col=\"1\" row=\"1\" row-span=\"2\" min-width=\"200\">\n <span slot=\"header\">Watchlist</span>\n <div class=\"demo-pane\">column, both rows</div>\n </c2-dash-card>\n <c2-dash-card col=\"2\" row=\"1\" min-height=\"60\">\n <span slot=\"header\">Price</span>\n <div class=\"demo-pane\">top right</div>\n </c2-dash-card>\n <c2-dash-card col=\"2\" row=\"2\">\n <span slot=\"header\">Orders</span>\n <div class=\"demo-pane\">bottom right</div>\n </c2-dash-card>\n</c2-dashboard>",
14802
+ "css": ".demo-grid {\n height: 220px;\n --c2-dashboard--gap: 10px;\n --c2-dashboard--padding: 10px;\n --c2-dashboard--background: var(--c2-theme--color-surface-container);\n --c2-dashboard--border-radius: var(--c2-theme--radius-lg);\n --c2-dash-card--background: var(--c2-theme--color-surface);\n --c2-dash-card--border: var(--c2-theme--border);\n --c2-dash-card--border-radius: var(--c2-theme--radius-md);\n --c2-dash-card__expanded--background: var(--c2-theme--color-surface);\n --c2-dash-card__header--border-bottom: var(--c2-theme--border);\n}\n\n.demo-pane {\n display: grid;\n height: 100%;\n place-items: center;\n font-size: 13px;\n color: var(--c2-theme--color-on-surface-variant);\n}"
14803
+ },
14804
+ {
14805
+ "kind": "usage",
14806
+ "label": "Expand controls, and a pane that cannot be resized",
14807
+ "html": "<c2-dashboard client:only=\"lit\" class=\"demo-grid\" columns=\"2\" rows=\"1\">\n <c2-dash-card col=\"1\" row=\"1\" expand-full>\n <span slot=\"header\">Chart</span>\n <div class=\"demo-pane\">expand me over the grid</div>\n </c2-dash-card>\n <c2-dash-card col=\"2\" row=\"1\" resize=\"none\">\n <div class=\"demo-pane\">resize=\"none\", controls float</div>\n </c2-dash-card>\n</c2-dashboard>",
14808
+ "css": ".demo-grid {\n height: 220px;\n --c2-dashboard--gap: 10px;\n --c2-dashboard--padding: 10px;\n --c2-dashboard--background: var(--c2-theme--color-surface-container);\n --c2-dashboard--border-radius: var(--c2-theme--radius-lg);\n --c2-dash-card--background: var(--c2-theme--color-surface);\n --c2-dash-card--border: var(--c2-theme--border);\n --c2-dash-card--border-radius: var(--c2-theme--radius-md);\n --c2-dash-card__expanded--background: var(--c2-theme--color-surface);\n --c2-dash-card__header--border-bottom: var(--c2-theme--border);\n}\n\n.demo-pane {\n display: grid;\n height: 100%;\n place-items: center;\n font-size: 13px;\n color: var(--c2-theme--color-on-surface-variant);\n}"
14809
+ },
14810
+ {
14811
+ "kind": "gallery",
14812
+ "label": "Trading desk",
14813
+ "section": "Presets",
14814
+ "description": "Trading desk Presets example for c2-dashboard.",
14815
+ "isDefault": false,
14816
+ "tags": [
14817
+ "c2-dashboard",
14818
+ "c2-dash-card",
14819
+ "c2-badge",
14820
+ "c2-list",
14821
+ "c2-list-item",
14822
+ "c2-icon-button",
14823
+ "c2-line-chart",
14824
+ "c2-chart-series",
14825
+ "c2-table",
14826
+ "c2-table-column"
14827
+ ],
14828
+ "html": "<c2-dashboard client:only=\"lit\" class=\"desk\" columns=\"260px 1fr\" rows=\"1fr 1fr\" storage-key=\"c2n-demo-desk\">\n <c2-dash-card col=\"1\" row=\"1\" row-span=\"2\" min-width=\"200\" card-id=\"watchlist\" expand-full>\n <span slot=\"header\">Watchlist</span>\n <c2-badge slot=\"actions\" tone=\"success\">Live</c2-badge>\n <c2-list value=\"aapl\">\n <c2-list-item value=\"aapl\"><span class=\"desk-quote\">AAPL <span class=\"desk-up\">+1.24%</span></span></c2-list-item>\n <c2-list-item value=\"msft\"><span class=\"desk-quote\">MSFT <span class=\"desk-up\">+0.62%</span></span></c2-list-item>\n <c2-list-item value=\"nvda\"><span class=\"desk-quote\">NVDA <span class=\"desk-down\">−2.08%</span></span></c2-list-item>\n <c2-list-item value=\"amzn\"><span class=\"desk-quote\">AMZN <span class=\"desk-up\">+0.41%</span></span></c2-list-item>\n <c2-list-item value=\"tsla\"><span class=\"desk-quote\">TSLA <span class=\"desk-down\">−1.13%</span></span></c2-list-item>\n </c2-list>\n <span slot=\"footer\">5 instruments</span>\n </c2-dash-card>\n\n <c2-dash-card col=\"2\" row=\"1\" min-height=\"120\" card-id=\"price\" expand-full>\n <span slot=\"header\">AAPL · quarterly revenue</span>\n <c2-icon-button slot=\"actions\" aria-label=\"Refresh\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"23 4 23 10 17 10\"></polyline><polyline points=\"1 20 1 14 7 14\"></polyline><path d=\"M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15\"></path></svg>\n </c2-icon-button>\n <c2-line-chart\n x-field=\"date\"\n x-type=\"time\"\n curve=\"smooth\"\n points=\"none\"\n legend=\"none\"\n data='[{\"date\":\"2023-12-30\",\"revenue\":119.575},{\"date\":\"2024-03-30\",\"revenue\":90.753},{\"date\":\"2024-06-29\",\"revenue\":85.777},{\"date\":\"2024-09-28\",\"revenue\":94.93},{\"date\":\"2024-12-28\",\"revenue\":124.3},{\"date\":\"2025-03-29\",\"revenue\":95.359},{\"date\":\"2025-06-28\",\"revenue\":94.036},{\"date\":\"2025-09-27\",\"revenue\":102.466}]'\n >\n <c2-chart-series field=\"revenue\" label=\"Revenue\"></c2-chart-series>\n </c2-line-chart>\n <span slot=\"footer\">USD billions · FY2024–25</span>\n </c2-dash-card>\n\n <c2-dash-card col=\"2\" row=\"2\" card-id=\"orders\" expand-full>\n <span slot=\"header\">Working orders</span>\n <c2-icon-button slot=\"controls\" aria-label=\"Order settings\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"12\" cy=\"12\" r=\"1\"></circle><circle cx=\"19\" cy=\"12\" r=\"1\"></circle><circle cx=\"5\" cy=\"12\" r=\"1\"></circle></svg>\n </c2-icon-button>\n <c2-table row-key=\"id\" rows='[{\"id\":\"1\",\"symbol\":\"AAPL\",\"side\":\"Buy\",\"qty\":1200,\"limit\":214.5,\"status\":\"Working\"},{\"id\":\"2\",\"symbol\":\"NVDA\",\"side\":\"Sell\",\"qty\":400,\"limit\":118.2,\"status\":\"Working\"},{\"id\":\"3\",\"symbol\":\"MSFT\",\"side\":\"Buy\",\"qty\":250,\"limit\":402.1,\"status\":\"Partial\"},{\"id\":\"4\",\"symbol\":\"TSLA\",\"side\":\"Sell\",\"qty\":900,\"limit\":241,\"status\":\"Working\"},{\"id\":\"5\",\"symbol\":\"AMZN\",\"side\":\"Buy\",\"qty\":150,\"limit\":186.75,\"status\":\"Queued\"}]'>\n <c2-table-column field=\"symbol\" header=\"Symbol\" width=\"100px\"></c2-table-column>\n <c2-table-column field=\"side\" header=\"Side\" width=\"80px\"></c2-table-column>\n <c2-table-column field=\"qty\" header=\"Qty\" width=\"1fr\" align=\"end\" format=\"number\"></c2-table-column>\n <c2-table-column field=\"limit\" header=\"Limit\" width=\"1fr\" align=\"end\" format=\"number\"></c2-table-column>\n <c2-table-column field=\"status\" header=\"Status\" width=\"110px\"></c2-table-column>\n </c2-table>\n <span slot=\"footer\">5 orders · updated 14:32</span>\n </c2-dash-card>\n</c2-dashboard>",
14829
+ "css": ".desk {\n height: 460px;\n --c2-dashboard--gap: 10px;\n --c2-dashboard--padding: 10px;\n --c2-dashboard--background: #f1f2f4;\n --c2-dashboard--border-radius: 14px;\n --c2-dash-card--background: #ffffff;\n --c2-dash-card--border: 1px solid #e4e4e7;\n --c2-dash-card--border-radius: 10px;\n --c2-dash-card__expanded--background: #ffffff;\n --c2-dash-card__header--min-height: 40px;\n --c2-dash-card__header--font-size: 13px;\n --c2-dash-card__header--border-bottom: 1px solid #e4e4e7;\n --c2-dash-card__footer--border-top: 1px solid #e4e4e7;\n}\n\n/* `body` is a part, so the pane's content area can be made to stretch whatever is inside it. */\n.desk c2-dash-card::part(body) {\n display: grid;\n min-height: 0;\n overflow: hidden;\n}\n\n.desk c2-line-chart {\n --c2-chart--height: 100%;\n --c2-chart--padding: 8px;\n --c2-chart--background: transparent;\n --c2-chart--border-top: none;\n --c2-chart--border-right: none;\n --c2-chart--border-bottom: none;\n --c2-chart--border-left: none;\n}\n\n.desk c2-table {\n width: 100%;\n height: 100%;\n --c2-table--border-top: none;\n --c2-table--border-right: none;\n --c2-table--border-bottom: none;\n --c2-table--border-left: none;\n --c2-table--font-size: 12px;\n}\n\n.desk c2-list {\n height: 100%;\n overflow: auto;\n --c2-list--border-top: none;\n --c2-list--border-right: none;\n --c2-list--border-bottom: none;\n --c2-list--border-left: none;\n --c2-list--padding-top: 6px;\n --c2-list--padding-bottom: 6px;\n}\n\n.desk-quote {\n display: flex;\n width: 100%;\n justify-content: space-between;\n gap: 12px;\n font-size: 13px;\n}\n\n.desk-up {\n color: #16a34a;\n}\n\n.desk-down {\n color: #dc2626;\n}"
14830
+ },
14831
+ {
14832
+ "kind": "gallery",
14833
+ "label": "Default",
14834
+ "section": "Presets",
14835
+ "description": "Default Presets example for c2-dashboard.",
14836
+ "isDefault": true,
14837
+ "tags": [
14838
+ "c2-dashboard",
14839
+ "c2-dash-card"
14840
+ ],
14841
+ "html": "<c2-dashboard client:only=\"lit\" class=\"bare\" columns=\"2\" rows=\"1\">\n <c2-dash-card col=\"1\" row=\"1\"><div class=\"bare-pane\">Pane one</div></c2-dash-card>\n <c2-dash-card col=\"2\" row=\"1\"><div class=\"bare-pane\">Pane two</div></c2-dash-card>\n</c2-dashboard>",
14842
+ "css": ".bare {\n height: 220px;\n padding: 10px;\n background: #f4f4f5;\n border-radius: 12px;\n}\n\n.bare-pane {\n display: grid;\n height: 100%;\n place-items: center;\n font-size: 13px;\n color: #71717a;\n background: #ffffff;\n border: 1px solid #e4e4e7;\n border-radius: 8px;\n}"
14843
+ },
14844
+ {
14845
+ "kind": "gallery",
14846
+ "label": "Seamless",
14847
+ "section": "Presets",
14848
+ "description": "Seamless Presets example for c2-dashboard.",
14849
+ "isDefault": false,
14850
+ "tags": [
14851
+ "c2-dashboard",
14852
+ "c2-dash-card"
14853
+ ],
14854
+ "html": "<c2-dashboard client:only=\"lit\" class=\"seamless\" columns=\"1fr 1fr 1fr\" rows=\"1\">\n <c2-dash-card col=\"1\" row=\"1\"><span slot=\"header\">Markets</span></c2-dash-card>\n <c2-dash-card col=\"2\" row=\"1\"><span slot=\"header\">Positions</span></c2-dash-card>\n <c2-dash-card col=\"3\" row=\"1\"><span slot=\"header\">Activity</span></c2-dash-card>\n</c2-dashboard>",
14855
+ "css": ".seamless {\n height: 220px;\n --c2-dashboard--gap: 1px;\n --c2-dashboard--padding: 1px;\n --c2-dashboard--background: #d4d4d8;\n --c2-dashboard--border-radius: 10px;\n --c2-dash-card--background: #ffffff;\n --c2-dash-card__expanded--background: #ffffff;\n --c2-dash-card__header--color: #52525b;\n --c2-dash-card__header--font-size: 13px;\n --c2-dash-card__header--min-height: 34px;\n --c2-dash-card__handle--size: 9px;\n --c2-dash-card__handle__hover--background: #0265dc;\n}"
14856
+ },
14857
+ {
14858
+ "kind": "gallery",
14859
+ "label": "Terminal",
14860
+ "section": "Presets",
14861
+ "description": "Terminal Presets example for c2-dashboard.",
14862
+ "isDefault": false,
14863
+ "tags": [
14864
+ "c2-dashboard",
14865
+ "c2-dash-card"
14866
+ ],
14867
+ "html": "<c2-dashboard client:only=\"lit\" class=\"terminal\" columns=\"1fr 2fr\" rows=\"1fr 1fr\">\n <c2-dash-card col=\"1\" row=\"1\" row-span=\"2\" expand-full>\n <span slot=\"header\">processes</span>\n </c2-dash-card>\n <c2-dash-card col=\"2\" row=\"1\" expand-full>\n <span slot=\"header\">output</span>\n </c2-dash-card>\n <c2-dash-card col=\"2\" row=\"2\">\n <span slot=\"header\">logs</span>\n </c2-dash-card>\n</c2-dashboard>",
14868
+ "css": ".terminal {\n height: 220px;\n --c2-dashboard--gap: 6px;\n --c2-dashboard--padding: 6px;\n --c2-dashboard--background: #09090b;\n --c2-dashboard--border-radius: 6px;\n --c2-dash-card--background: #18181b;\n --c2-dash-card--border: 1px solid #27272a;\n --c2-dash-card--border-radius: 4px;\n --c2-dash-card__expanded--background: #18181b;\n --c2-dash-card__header--color: #a1a1aa;\n --c2-dash-card__header--font-size: 12px;\n --c2-dash-card__header--min-height: 28px;\n --c2-dash-card__header--border-bottom: 1px solid #27272a;\n --c2-dash-card__control--color: #71717a;\n --c2-dash-card__control__hover--background: #27272a;\n --c2-dash-card__control__hover--color: #fafafa;\n --c2-dash-card__handle__hover--background: #22c55e;\n --c2-dash-card__handle__active--background: #4ade80;\n}"
14869
+ },
14870
+ {
14871
+ "kind": "gallery",
14872
+ "label": "Soft",
14873
+ "section": "Presets",
14874
+ "description": "Soft Presets example for c2-dashboard.",
14875
+ "isDefault": false,
14876
+ "tags": [
14877
+ "c2-dashboard",
14878
+ "c2-dash-card"
14879
+ ],
14880
+ "html": "<c2-dashboard client:only=\"lit\" class=\"soft\" columns=\"1fr 1fr\" rows=\"1\">\n <c2-dash-card col=\"1\" row=\"1\" expand-full><span slot=\"header\">Revenue</span></c2-dash-card>\n <c2-dash-card col=\"2\" row=\"1\" expand-full><span slot=\"header\">Churn</span></c2-dash-card>\n</c2-dashboard>",
14881
+ "css": ".soft {\n height: 220px;\n --c2-dashboard--gap: 14px;\n --c2-dashboard--padding: 14px;\n --c2-dashboard--background: #f1f2f4;\n --c2-dashboard--border-radius: 18px;\n --c2-dash-card--background: #ffffff;\n --c2-dash-card--border-radius: 14px;\n --c2-dash-card--box-shadow: 0 1px 2px rgba(9, 9, 11, 0.06), 0 8px 24px rgba(9, 9, 11, 0.08);\n --c2-dash-card__expanded--background: #ffffff;\n --c2-dash-card__header--font-weight: 500;\n --c2-dash-card__handle__hover--background: rgba(9, 9, 11, 0.18);\n --c2-dash-card__handle__active--background: rgba(9, 9, 11, 0.38);\n}"
14882
+ },
14883
+ {
14884
+ "kind": "preview",
14885
+ "label": "Preview",
14886
+ "html": "<c2-dashboard columns=\"1fr 1fr\" rows=\"1fr 1fr\" style=\"width:260px;height:150px;--c2-dashboard--gap:6px;--c2-dashboard--padding:6px;--c2-dashboard--background:var(--c2-theme--color-surface-container);--c2-dashboard--border-radius:10px;--c2-dash-card--background:var(--c2-theme--color-surface);--c2-dash-card--border:var(--c2-theme--border);--c2-dash-card--border-radius:6px;--c2-dash-card__header--font-size:11px;--c2-dash-card__header--min-height:0;--c2-dash-card__header--padding-block:6px;--c2-dash-card__header--padding-inline:8px\">\n <c2-dash-card col=\"1\" row=\"1\" row-span=\"2\"><span slot=\"header\">Watchlist</span></c2-dash-card>\n <c2-dash-card col=\"2\" row=\"1\"><span slot=\"header\">Price</span></c2-dash-card>\n <c2-dash-card col=\"2\" row=\"2\"><span slot=\"header\">Orders</span></c2-dash-card>\n</c2-dashboard>"
14887
+ }
14888
+ ],
14889
+ "hasGallery": true
14890
+ },
14065
14891
  "date-input": {
14066
14892
  "id": "date-input",
14067
14893
  "package": "@c2n/date-input",
@@ -49472,6 +50298,8 @@
49472
50298
  "c2-color-select": "color-select",
49473
50299
  "c2-color-slider": "color-slider",
49474
50300
  "c2-copy-button": "copy-button",
50301
+ "c2-dash-card": "dashboard",
50302
+ "c2-dashboard": "dashboard",
49475
50303
  "c2-date-input": "date-input",
49476
50304
  "c2-date-selector": "date-selector",
49477
50305
  "c2-details": "details",
@@ -49557,6 +50385,7 @@
49557
50385
  "@c2n/color-select": "color-select",
49558
50386
  "@c2n/color-slider": "color-slider",
49559
50387
  "@c2n/copy-button": "copy-button",
50388
+ "@c2n/dashboard": "dashboard",
49560
50389
  "@c2n/date-input": "date-input",
49561
50390
  "@c2n/date-selector": "date-selector",
49562
50391
  "@c2n/details": "details",
@@ -49622,7 +50451,7 @@
49622
50451
  "light": "#0265dc",
49623
50452
  "dark": "#5aa3ff",
49624
50453
  "description": "Accent colour: filled buttons, selected states, focused borders, links.",
49625
- "usedBy": 56
50454
+ "usedBy": 57
49626
50455
  },
49627
50456
  {
49628
50457
  "name": "--c2-theme--color-primary-hover",
@@ -49662,7 +50491,7 @@
49662
50491
  "light": "rgba(2, 101, 220, 0.2)",
49663
50492
  "dark": "rgba(90, 163, 255, 0.28)",
49664
50493
  "description": "Accent tint for luminous borders and decorative glows.",
49665
- "usedBy": 0
50494
+ "usedBy": 1
49666
50495
  },
49667
50496
  {
49668
50497
  "name": "--c2-theme--color-surface",
@@ -49670,7 +50499,7 @@
49670
50499
  "light": "#ffffff",
49671
50500
  "dark": "#18181b",
49672
50501
  "description": "Default surface of inputs, lists, cards, dialogs.",
49673
- "usedBy": 47
50502
+ "usedBy": 48
49674
50503
  },
49675
50504
  {
49676
50505
  "name": "--c2-theme--color-surface-container-low",
@@ -49686,7 +50515,7 @@
49686
50515
  "light": "#f4f4f5",
49687
50516
  "dark": "#27272a",
49688
50517
  "description": "Hover surface for rows and icon buttons.",
49689
- "usedBy": 34
50518
+ "usedBy": 35
49690
50519
  },
49691
50520
  {
49692
50521
  "name": "--c2-theme--color-on-surface",
@@ -49694,7 +50523,7 @@
49694
50523
  "light": "#18181b",
49695
50524
  "dark": "#f4f4f5",
49696
50525
  "description": "Primary text colour.",
49697
- "usedBy": 61
50526
+ "usedBy": 63
49698
50527
  },
49699
50528
  {
49700
50529
  "name": "--c2-theme--color-on-surface-variant",
@@ -49702,7 +50531,7 @@
49702
50531
  "light": "#71717a",
49703
50532
  "dark": "#a1a1aa",
49704
50533
  "description": "Secondary text, placeholders, icons, supporting text.",
49705
- "usedBy": 94
50534
+ "usedBy": 96
49706
50535
  },
49707
50536
  {
49708
50537
  "name": "--c2-theme--color-outline",
@@ -49772,14 +50601,14 @@
49772
50601
  "category": "font",
49773
50602
  "light": "12px",
49774
50603
  "description": "Small text: supporting text, tooltips, descriptions, timestamps.",
49775
- "usedBy": 34
50604
+ "usedBy": 35
49776
50605
  },
49777
50606
  {
49778
50607
  "name": "--c2-theme--font-size-md",
49779
50608
  "category": "font",
49780
50609
  "light": "14px",
49781
50610
  "description": "Body text: buttons, inputs, list items, dialog content.",
49782
- "usedBy": 44
50611
+ "usedBy": 45
49783
50612
  },
49784
50613
  {
49785
50614
  "name": "--c2-theme--font-weight-medium",
@@ -49793,7 +50622,7 @@
49793
50622
  "category": "font",
49794
50623
  "light": "600",
49795
50624
  "description": "Semibold weight: dialog titles, list headings, avatars.",
49796
- "usedBy": 21
50625
+ "usedBy": 22
49797
50626
  },
49798
50627
  {
49799
50628
  "name": "--c2-theme--radius-sm",
@@ -49807,7 +50636,7 @@
49807
50636
  "category": "radius",
49808
50637
  "light": "6px",
49809
50638
  "description": "Default radius: buttons, inputs, list items, tooltips.",
49810
- "usedBy": 50
50639
+ "usedBy": 51
49811
50640
  },
49812
50641
  {
49813
50642
  "name": "--c2-theme--radius-lg",
@@ -49828,7 +50657,7 @@
49828
50657
  "category": "radius",
49829
50658
  "light": "999px",
49830
50659
  "description": "Pill / circle radius: avatars, icon buttons.",
49831
- "usedBy": 19
50660
+ "usedBy": 20
49832
50661
  },
49833
50662
  {
49834
50663
  "name": "--c2-theme--border-width",
@@ -49850,7 +50679,7 @@
49850
50679
  "light": "2px solid rgba(2, 101, 220, 0.4)",
49851
50680
  "dark": "2px solid rgba(90, 163, 255, 0.5)",
49852
50681
  "description": "Focus-visible outline of every component.",
49853
- "usedBy": 37
50682
+ "usedBy": 39
49854
50683
  },
49855
50684
  {
49856
50685
  "name": "--c2-theme--disabled-opacity",
@@ -49864,7 +50693,7 @@
49864
50693
  "category": "motion",
49865
50694
  "light": "1",
49866
50695
  "description": "Multiplier applied to every transition and animation duration (0 disables motion).",
49867
- "usedBy": 19
50696
+ "usedBy": 23
49868
50697
  },
49869
50698
  {
49870
50699
  "name": "--c2-theme--shadow-md",
@@ -50251,6 +51080,25 @@
50251
51080
  "--c2-copy-button__container__focus--outline": "--c2-theme--focus-ring",
50252
51081
  "--c2-copy-button__container__disabled--opacity": "--c2-theme--disabled-opacity",
50253
51082
  "--c2-copy-button--transition-duration": "--c2-theme--motion-scale",
51083
+ "--c2-dash-card__expanded--background": "--c2-theme--color-surface",
51084
+ "--c2-dash-card__enter--animation-duration": "--c2-theme--motion-scale",
51085
+ "--c2-dash-card__leave--animation-duration": "--c2-theme--motion-scale",
51086
+ "--c2-dash-card__expanded--animation-duration": "--c2-theme--motion-scale",
51087
+ "--c2-dash-card__header--color": "--c2-theme--color-on-surface",
51088
+ "--c2-dash-card__header--font-size": "--c2-theme--font-size-md",
51089
+ "--c2-dash-card__header--font-weight": "--c2-theme--font-weight-semibold",
51090
+ "--c2-dash-card__footer--color": "--c2-theme--color-on-surface-variant",
51091
+ "--c2-dash-card__footer--font-size": "--c2-theme--font-size-sm",
51092
+ "--c2-dash-card__control--border-radius": "--c2-theme--radius-md",
51093
+ "--c2-dash-card__control--color": "--c2-theme--color-on-surface-variant",
51094
+ "--c2-dash-card__control__hover--background": "--c2-theme--color-surface-container",
51095
+ "--c2-dash-card__control__hover--color": "--c2-theme--color-on-surface",
51096
+ "--c2-dash-card__control__focus--outline": "--c2-theme--focus-ring",
51097
+ "--c2-dash-card__handle__hover--background": "--c2-theme--color-primary-glow",
51098
+ "--c2-dash-card__handle__active--background": "--c2-theme--color-primary",
51099
+ "--c2-dash-card__handle--border-radius": "--c2-theme--radius-full",
51100
+ "--c2-dash-card__handle--transition-duration": "--c2-theme--motion-scale",
51101
+ "--c2-dash-card__handle__focus--outline": "--c2-theme--focus-ring",
50254
51102
  "--c2-date-input--border": "--c2-theme--border",
50255
51103
  "--c2-date-input--border-radius": "--c2-theme--radius-md",
50256
51104
  "--c2-date-input--color": "--c2-theme--color-on-surface",
@@ -50890,6 +51738,6 @@
50890
51738
  "workflow": "# The c2n application workflow\n\nBuild screens from `@c2n/*` web components with as little code as possible. Three layers, applied in this order.\n\n## 1. Theme once\n\n- Install `@c2n/theme` next to the component packages you use.\n- Import `@c2n/theme/theme.css` once at the application root (tokens + base theme). If the app already owns a token system, import only `@c2n/theme/base.css` and bridge your tokens onto the `--c2-theme--*` names.\n- Override the tokens that differ from the defaults on `:root` (light) and under your dark-mode selector. About 35 tokens (`--c2-theme--color-primary`, `--c2-theme--radius-md`, `--c2-theme--font-family`, `--c2-theme--focus-ring`, …) drive every component.\n- Never set component variables globally when a token exists for the job.\n\n## 2. Use the tags directly\n\n- Register an element with a side-effect import (`import '@c2n/button'`) at the application entry, or in the module that renders it.\n- Write plain markup: `<c2-button>Save</c2-button>`. Attributes, slots and events come from the component API (MCP `get_component`, or `node_modules/@c2n/<name>/custom-elements.json`).\n- Retrieve `get_examples` next: begin from the unmodified Default sample, then select gallery examples by use case. Use `get_presets` when structured values are more useful than a complete pattern.\n- Icons are components: `c2-feather-<name>` from `@c2n/feather-icons/icons/<name>.js`, sized and coloured through `--c2-feather-icon--size|color|stroke-width`.\n- A component that appears once with the themed default look needs nothing else.\n\n## 3. Name what repeats\n\nThe decision rule, cheapest first:\n\n| Situation | Do this |\n| --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |\n| The element appears once, default look is fine | plain tag |\n| Same look repeats, markup is otherwise plain | **CSS-class variant**: a class that sets `--c2-<component>__…` variables |\n| Same look **and** the same attributes / slots / accessible name repeat | **wrapper component** in your framework (Astro/React/Vue/Lit) that renders the c2 element |\n| The variant must be its own tag (used from strings, other Lit templates, shipped) | **Lit subclass** of the component with the variables baked into `static styles` |\n| Several c2 components plus some logic repeat | **composed component**: children's variables set on `:host`/a class, attributes forwarded, events re-emitted |\n| No c2 component fits | app-level component styled with the same `--c2-theme--*` tokens; avoid patching installed packages locally |\n\nEvery variant lives in one directory (`src/components/ui/`, `src/ui/`…), one file per variant, under the app's own prefix (`app-*`, `site-*`, `my-*`), never `c2-*`.\n\n## 4. Verify\n\n- Every element used is registered (no `HTMLUnknownElement`, no empty tags).\n- `@c2n/theme` is imported exactly once; tokens overridden on `:root` and the dark selector.\n- Prefer CSS custom properties. Every `::part()` selector must name a CSS part documented by `get_component`; no repeated inline `style=\"--c2-…\"`.\n- Every variable, attribute, slot and event name exists in the component API.\n- Variant tags contain a hyphen and do not start with `c2-`.\n- Light and dark both look right; build, lint and type-check pass.\n",
50891
51739
  "theming": "# Theming c2n components\n\n## Layers\n\n1. **Tokens** `--c2-theme--<name>` (from `@c2n/theme/tokens.css`, ~35 of them). Set by the application.\n2. **Base theme** `@c2n/theme/base.css`: `--c2-<component>__<part>--<prop>: var(--c2-theme--<token>, <component default>)` on `:root`/`:host` for every mapped component variable. Generated from the component manifests.\n3. **Component variables** `--c2-<component>__<part>[__<state>]--<property>`: the fine-grained escape hatch. Set on an element, a class or any ancestor; they always win over the base theme.\n4. **Variant components** built from 2 and 3.\n\n## Install\n\n```ts\nimport '@c2n/theme/theme.css' // tokens + base theme, once\n```\n\n```css\n:root {\n --c2-theme--color-primary: #7c3aed;\n --c2-theme--color-primary-hover: #6d28d9;\n --c2-theme--radius-md: 10px;\n --c2-theme--font-family: 'Inter', system-ui, sans-serif;\n}\n```\n\n## Bring your own tokens\n\n```css\n@import '@c2n/theme/base.css';\n:root {\n --c2-theme--color-primary: var(--brand-600);\n --c2-theme--color-on-primary: var(--brand-on-600);\n --c2-theme--color-surface: var(--surface);\n --c2-theme--color-on-surface: var(--text);\n --c2-theme--color-outline: var(--border);\n --c2-theme--radius-md: var(--radius);\n --c2-theme--font-family: var(--font-sans);\n --c2-theme--focus-ring: 2px solid var(--brand-600);\n}\n```\n\nDark mode then follows the app's own switch because the bridged values flip.\n\n## Dark mode with the shipped tokens\n\n`tokens.css` sets light values on `:root` and dark values under `[data-theme='dark']` and `.c2-dark`, with `prefers-color-scheme: dark` as the fallback when no `data-theme` attribute is present. `data-theme=\"light\"` / `.c2-light` opts a subtree out. Selectors are not tied to the root element, so any subtree can be inverted.\n\n## Token groups\n\n- Colour roles: `color-primary`, `color-primary-hover`, `color-primary-active`, `color-on-primary`, `color-primary-container`, `color-surface`, `color-surface-container-low`, `color-surface-container`, `color-on-surface`, `color-on-surface-variant`, `color-outline`, `color-outline-variant`, `color-outline-strong`, `color-error`, `color-scrim`, `color-inverse-surface`, `color-on-inverse-surface`.\n- Typography: `font-family` (unset by default: components inherit the page font), `font-size-sm|md`, `font-weight-medium|semibold`.\n- Shape: `radius-sm|md|lg|xl|full`.\n- Borders: `border-width`, `border` (composite: the whole resting border shorthand; falls back to `border-width solid color-outline`).\n- Interaction: `focus-ring` (outline shorthand), `disabled-opacity`, `motion-scale` (multiplies every duration; `0` disables motion).\n- Elevation: `shadow-md`, `shadow-lg`.\n\nComposite tokens wrap their primitives: `var(--c2-theme--border, var(--c2-theme--border-width, 1px) solid var(--c2-theme--color-outline, #bcbcc6))`, so set the shorthand or just the colour.\n\n## What the base theme does not cover\n\nSizes, paddings, gaps, identity colours (avatar fallbacks), status colours, the code viewer's syntax theme, and variables without a default (they inherit). Use component variables or a variant for those. `@c2n/theme/report.json` lists what is mapped per package; MCP `get_theme` with a `tag` shows the mapping of one component.\n\n## Grammar and states\n\n`--c2-<component>__<part>[__<state>]--<property>`: `__` separates component / part / state, `--` separates the CSS property. States: `hover`, `active`, `focus`, `selected`, `disabled`, `open`, `error`, `read-only`. Example: `--c2-checkbox__container__selected--background-color`.\n",
50892
51740
  "variant-components": "# Variant and composed components\n\nA variant is one c2 component with a fixed look (CSS variables) and, sometimes, fixed attributes, slots or accessible name. A composed component is several c2 components plus glue. Both normally set children's CSS variables on the host element or a class. Use `::part()` only for a part documented by `get_component` and only when the public variables cannot express the change.\n\n## Shape 1: CSS-class variant\n\n```css\n.danger-button {\n --c2-button__container--background-color: var(--c2-theme--color-error);\n --c2-button__container__hover--background-color: color-mix(in srgb, var(--c2-theme--color-error), black 12%);\n}\n```\n\n```html\n<c2-button class=\"danger-button\">Delete</c2-button>\n```\n\nUse when only the look differs. Keep variant classes in one stylesheet (`ui/variants.css`). Read variable names from the component API; do not invent them.\n\n## Shape 2: wrapper component\n\nWhen attributes, slots or the accessible name repeat as well. Framework-native, zero runtime cost beyond the c2 element. Example (Astro; the same idea in React/Vue/Svelte):\n\n```astro\n---\n// SiteIconButton.astro — c2-icon-button with the app's size and a tooltip that defaults to the label.\ninterface Props {\n label: string\n size?: 'sm' | 'md'\n class?: string\n [attr: string]: unknown\n}\nconst { label, size = 'md', class: className = '', ...rest } = Astro.props\n---\n\n<c2-icon-button class={`site-icon-button site-icon-button--${size} ${className}`} aria-label={label} tooltip={label} {...rest}>\n <slot />\n</c2-icon-button>\n<style is:global>\n .site-icon-button {\n --c2-icon-button--border-radius: var(--c2-theme--radius-sm);\n --c2-icon-button__hover--background-color: var(--c2-theme--color-surface-container);\n }\n .site-icon-button--sm {\n --c2-icon-button__state-layer--size: 30px;\n --c2-icon-button__icon--width: 16px;\n --c2-icon-button__icon--height: 16px;\n }\n .site-icon-button--md {\n --c2-icon-button__state-layer--size: 36px;\n --c2-icon-button__icon--width: 18px;\n --c2-icon-button__icon--height: 18px;\n }\n</style>\n```\n\nForward unknown props as attributes (`{...rest}`) so callers keep the full c2 API (`disabled`, `data-*`, `aria-*`).\n\n## Shape 3: Lit subclass\n\nWhen the variant must be a tag of its own. The docs studio's Code tab and MCP `generate_variant` produce this:\n\n```ts\nimport { css } from 'lit'\nimport { Button } from '@c2n/button'\n\nexport class DangerButton extends Button {\n static override styles = [\n Button.styles,\n css`\n :host {\n --c2-button__container--background-color: var(--c2-theme--color-error);\n }\n `,\n ]\n override connectedCallback() {\n super.connectedCallback()\n this.setAttribute('running', '') // fixed attributes go here\n }\n}\nif (!customElements.get('app-danger-button')) customElements.define('app-danger-button', DangerButton)\n```\n\nImport the class from the module that defines the element (`@c2n/tabs/tab.js` for `c2-tab`, `@c2n/feather-icons/icons/<name>.js` for icons). Importing it also registers the original `c2-*` tag, which is fine. Never `customElements.define` a `c2-` name.\nGuard registration with `customElements.get()` so development HMR or repeated module evaluation cannot define the same tag twice.\n\n## Composed components\n\nSeveral c2 components and some logic repeat: a search field (`c2-text-field` + `c2-list`), a settings dialog (`c2-modal` + form controls), a toolbar (`c2-icon-button`s + `c2-tooltip`s).\n\n- Set the children's variables on the composed component's class or `:host` (custom properties inherit through shadow boundaries): `.search-palette__field { --c2-text-field--border-top: none; }`.\n- Forward the attributes callers should control as properties/attributes of the composed component.\n- Re-emit the child events callers need. In Lit use `redispatchEvent(this, event)` from `@c2n/core/dom-helper.js`; elsewhere `dispatchEvent(new CustomEvent(...))`.\n- Let the primitives keep their responsibilities (a `c2-modal` already traps focus, closes on Escape and backdrop click, locks scrolling and restores focus): write only the glue.\n- Declare composition in JSDoc (`@internalcomponent c2-list`, `@slotcomponent c2-list-item`) when the composed component is itself a Lit element with a manifest.\n\n## Naming and placement\n\n- Own prefix: `app-*`, `site-*`, `my-*`. A custom element name must contain a hyphen.\n- One file per variant, one directory (`src/components/ui/`), exported from a barrel.\n- Three-line header comment: what it wraps, which variables it fixes, where it is used.\n",
50893
- "frameworks": "# Using c2n components per framework\n\nAll components are standard custom elements (Lit 3). Register with a side-effect import; then they are plain HTML.\n\n## Events (every framework)\n\nEach component that fires events exports an event map (`TableEventMap`, `SelectEventMap`, …) from the same module as its class, and declares typed `addEventListener` overloads, so the detail narrows with no cast:\n\n```ts\ntable.addEventListener('selection-change', (event) => event.detail.rows) // TableRow[]\n```\n\n`EventMapOf<T>` from `@c2n/core/event-helper.js` recovers a component's map for code that is generic over elements. Use the map type instead of hand-writing `CustomEvent<{ value: string[] }>`.\n\n`selection-change` **does not bubble** — `c2-list`, `c2-select`, `c2-table`, `c2-tabs` and `c2-virtual-list` all fire it, so a listener goes on the element itself, never on an ancestor. `c2-tabs` fires `selection-change`, not `change`.\n\nEvery form-associated component fires plain `input` and `change` alongside its semantic event, which is what generic two-way bindings listen for.\n\nA duplicate `customElements.define` warns and keeps the first definition instead of throwing.\n\n## Plain HTML / Vite / any bundler\n\n```html\n<script type=\"module\">\n import '@c2n/theme/theme.css'\n import '@c2n/button'\n</script>\n<c2-button>Save</c2-button>\n```\n\nWith a bundler, put the imports in the entry module (`main.ts`). CSS imports work through the bundler's CSS handling.\n\n## Lit\n\nImport what you render at the top of the component module (`import '@c2n/text-field'`). Extend a component for a tag variant (`class AppField extends TextField`). Re-emit child events with `redispatchEvent` from `@c2n/core/dom-helper.js`. Set child variables in your `static styles` on `:host` or on a class.\n\n## Astro\n\n- Islands (`@astrojs/lit`): `import { Button } from '@c2n/button'` in the frontmatter, `<Button client:load>` in the template. SSR'd with declarative shadow DOM, hydrated on load. Pass **kebab-case attributes** only (a prop whose name matches an element property is set as a property and forces `defer-hydration`). A `client:only` island must not contain islands: its children end up in a `<template>` and nothing hydrates; the parent module registers the children instead.\n- Plain tags + client script: `<c2-button>` in the template and `import '@c2n/button'` inside a `<script>`. Cheaper for repeated markup (no shadow-DOM copy per instance); guard the flash with `c2-button:not(:defined) { visibility: hidden }`.\n- Scoped `<style>` does not reach elements rendered by child components; use `is:global` (or `:global()`) for variant classes.\n\n## React 19\n\nCustom elements work as JSX tags. React 19 passes primitive props as attributes and functions as event listeners for `on*` names; for custom events attach listeners with a `ref` (`ref.current.addEventListener('selection-change', …)`).\n\nTypes: `import '@c2n/<name>/react'` — one line per package, in any `.d.ts` — declares the tags in `JSX.IntrinsicElements` with props derived from the element class. Do not hand-write the mapping. React 18 and older: pass attributes as strings and use refs for events and properties.\n\n## Vue 3\n\nTell the compiler about the tags: `compilerOptions.isCustomElement = (tag) => tag.startsWith('c2-')` (in `@vitejs/plugin-vue`'s `template.compilerOptions`); without it every `c2-*` tag is treated as a Vue component and renders nothing. Register the elements at module scope before `mount()`: Vue chooses between a property and an attribute with `key in el`, so a binding on an element that has not upgraded yet falls back to an attribute.\n\nTypes: `import '@c2n/<name>/vue'` registers the tags with Volar, and `\"extends\": [..., \"@c2n/framework-types/tsconfig.vue.json\"]` supplies the matching `vueCompilerOptions` (`strictTemplates`, plus the `v-model` prop mapping so `v-model` binds `value`/`checked` rather than `modelValue`). Declare no local `vueCompilerOptions` next to it — a local one replaces the inherited object rather than merging.\n\n- Events: `@selection-change`, `@submit-message` bind by their real kebab-case name — Vue calls `addEventListener` with the name as written. The handler gets a plain `Event`, so narrow it (`(event as CustomEvent<{ value: string[] }>).detail`).\n- `v-model` works on `c2-text-field` / `c2-textarea`: on a custom element Vue compiles it to the plain-text model directive, which sets `el.value` and listens for `input`, and both components expose `value` and re-emit the native `input` event.\n- `.prop` forces a DOM property (`:value.prop=\"selected\"` for array/object values); `.attr` forces an attribute (`:align.attr=\"side\"`), needed when a property is not reflected but the component styles it with `:host([attr])` — `c2-chat-message`'s `align` is the case to know.\n- A static attribute stays an attribute, so spell it the way the component declares it (`row-key`, not `rowKey`).\n\n## Angular\n\n`CUSTOM_ELEMENTS_SCHEMA` on the component is the only required configuration. `[rows]=\"…\"` writes a property with `setProperty`; `(selection-change)` binds the event by its real name. A **static** attribute stays an attribute, so a camelCase property needs `[rowKey]=\"'id'\"` or the real attribute name (`row-key`) — the lowercase spelling `rowkey` is ignored and logs a warning.\n\nForms: Angular's built-in value accessors match `input`/`select`/`textarea` only, so `ngModel` and `formControlName` do nothing on a c2 control without `@c2n/angular`. Add `imports: [FormsModule, ...C2_FORM_ACCESSORS]`.\n\nThe schema turns off template type checking, so `$event` is a bare `Event`: take the component's event-map type in the handler rather than `$any` at the call site.\n\n## Svelte\n\nSvelte binds attributes and `on:` events directly.\n\n## Table cells\n\n`renderCell` cannot return framework markup (it is handed to Lit). Mark the column `cell-slot` and render one light-DOM child per row into `slot=\"cell:<row key>:<field>\"`; the children stay in the document, so ordinary CSS reaches them. Requires `row-key`; `renderCell`/the column format is the fallback.\n\n## Editor support outside TypeScript\n\n`@c2n/framework-types` ships `dist/html-custom-data.json` (point `html.customData` at it for VS Code / Volar) and `dist/web-types.json` (picked up automatically by the JetBrains IDEs). Both are generated from the custom-elements manifests, and cover plain HTML, Angular templates and Vue SFCs.\n\n## Server-side rendering and static HTML\n\n- Components must not touch `document`/`window` at module scope; the c2 components guard with `isServer`.\n- Without SSR of the shadow DOM, hide unregistered tags until they upgrade: `c2-modal:not(:defined) { display: none }` (dialogs, lists) or `visibility: hidden` (layout-stable chrome).\n- Theme CSS is plain CSS; load it in the document head so the first paint is themed.\n"
51741
+ "frameworks": "# Using c2n components per framework\n\nAll components are standard custom elements (Lit 3). Register with a side-effect import; then they are plain HTML.\n\n## Events (every framework)\n\nEach component that fires events exports an event map (`TableEventMap`, `SelectEventMap`, …) from the same module as its class, and declares typed `addEventListener` overloads, so the detail narrows with no cast:\n\n```ts\ntable.addEventListener('selection-change', (event) => event.detail.rows) // TableRow[]\n```\n\n`EventMapOf<T>` from `@c2n/core/event-helper.js` recovers a component's map for code that is generic over elements. Use the map type instead of hand-writing `CustomEvent<{ value: string[] }>`.\n\n`selection-change` **does not bubble** — `c2-list`, `c2-select`, `c2-table`, `c2-tabs` and `c2-virtual-list` all fire it, so a listener goes on the element itself, never on an ancestor. `c2-tabs` fires `selection-change`, not `change`.\n\nEvery form-associated component fires plain `input` and `change` alongside its semantic event, which is what generic two-way bindings listen for.\n\nA duplicate `customElements.define` warns and keeps the first definition instead of throwing.\n\n## Plain HTML / Vite / any bundler\n\n```html\n<script type=\"module\">\n import '@c2n/theme/theme.css'\n import '@c2n/button'\n</script>\n<c2-button>Save</c2-button>\n```\n\nWith a bundler, put the imports in the entry module (`main.ts`). CSS imports work through the bundler's CSS handling.\n\n## Lit\n\nImport what you render at the top of the component module (`import '@c2n/text-field'`). Extend a component for a tag variant (`class AppField extends TextField`). Re-emit child events with `redispatchEvent` from `@c2n/core/dom-helper.js`. Set child variables in your `static styles` on `:host` or on a class.\n\n## Astro\n\n- Islands (`@astrojs/lit`): `import { Button } from '@c2n/button'` in the frontmatter, `<Button client:load>` in the template. SSR'd with declarative shadow DOM, hydrated on load. Pass **kebab-case attributes** only (a prop whose name matches an element property is set as a property and forces `defer-hydration`). A `client:only` island must not contain islands: its children end up in a `<template>` and nothing hydrates; the parent module registers the children instead.\n- Plain tags + client script: `<c2-button>` in the template and `import '@c2n/button'` inside a `<script>`. Cheaper for repeated markup (no shadow-DOM copy per instance); guard the flash with `c2-button:not(:defined) { visibility: hidden }`.\n- Scoped `<style>` does not reach elements rendered by child components; use `is:global` (or `:global()`) for variant classes.\n\n## React 19\n\nCustom elements work as JSX tags. React 19 passes primitive props as attributes and functions as event listeners for `on*` names; for custom events attach listeners with a `ref` (`ref.current.addEventListener('selection-change', …)`).\n\nTypes: `import '@c2n/<name>/react'` — one line per package, in any `.d.ts` — declares the tags in `JSX.IntrinsicElements` with props derived from the element class, plus each kebab-case attribute name (`row-key` next to `rowKey`). Do not hand-write the mapping. React 18 and older: pass attributes as strings and use refs for events and properties.\n\n**Server-rendered React (Next.js, React Router SSR):** write a camelCase property by its kebab-case attribute name — `min-width`, `expand-full`, `storage-key`, not `minWidth`. The server writes a custom element's props into the HTML verbatim, the parser lowercases them (`minwidth`) and hydration does not set properties, so the camelCase spelling reaches the element as an attribute it does not declare. The component forwards that lookalike to the real attribute and logs a warning, so the value is not lost, but the kebab-case name is what the types list and what needs no forwarding. Object and array props (`rows`) stringify on the server: set them in an effect through a ref.\n\n## Vue 3\n\nTell the compiler about the tags: `compilerOptions.isCustomElement = (tag) => tag.startsWith('c2-')` (in `@vitejs/plugin-vue`'s `template.compilerOptions`); without it every `c2-*` tag is treated as a Vue component and renders nothing. Register the elements at module scope before `mount()`: Vue chooses between a property and an attribute with `key in el`, so a binding on an element that has not upgraded yet falls back to an attribute.\n\nTypes: `import '@c2n/<name>/vue'` registers the tags with Volar, and `\"extends\": [..., \"@c2n/framework-types/tsconfig.vue.json\"]` supplies the matching `vueCompilerOptions` (`strictTemplates`, plus the `v-model` prop mapping so `v-model` binds `value`/`checked` rather than `modelValue`). Declare no local `vueCompilerOptions` next to it — a local one replaces the inherited object rather than merging.\n\n- Events: `@selection-change`, `@submit-message` bind by their real kebab-case name — Vue calls `addEventListener` with the name as written. The handler gets a plain `Event`, so narrow it (`(event as CustomEvent<{ value: string[] }>).detail`).\n- `v-model` works on `c2-text-field` / `c2-textarea`: on a custom element Vue compiles it to the plain-text model directive, which sets `el.value` and listens for `input`, and both components expose `value` and re-emit the native `input` event.\n- `.prop` forces a DOM property (`:value.prop=\"selected\"` for array/object values); `.attr` forces an attribute (`:align.attr=\"side\"`), needed when a property is not reflected but the component styles it with `:host([attr])` — `c2-chat-message`'s `align` is the case to know.\n- A static attribute stays an attribute, so spell it the way the component declares it (`row-key`, not `rowKey`).\n\n## Angular\n\n`CUSTOM_ELEMENTS_SCHEMA` on the component is the only required configuration. `[rows]=\"…\"` writes a property with `setProperty`; `(selection-change)` binds the event by its real name. A **static** attribute stays an attribute, so a camelCase property needs `[rowKey]=\"'id'\"` or the real attribute name (`row-key`) — the lowercase spelling `rowkey` is forwarded to `row-key` with a warning.\n\nForms: Angular's built-in value accessors match `input`/`select`/`textarea` only, so `ngModel` and `formControlName` do nothing on a c2 control without `@c2n/angular`. Add `imports: [FormsModule, ...C2_FORM_ACCESSORS]`.\n\nThe schema turns off template type checking, so `$event` is a bare `Event`: take the component's event-map type in the handler rather than `$any` at the call site.\n\n## Svelte\n\nSvelte binds attributes and `on:` events directly.\n\n## Table cells\n\n`renderCell` cannot return framework markup (it is handed to Lit). Mark the column `cell-slot` and render one light-DOM child per row into `slot=\"cell:<row key>:<field>\"`; the children stay in the document, so ordinary CSS reaches them. Requires `row-key`; `renderCell`/the column format is the fallback.\n\n## Editor support outside TypeScript\n\n`@c2n/framework-types` ships `dist/html-custom-data.json` (point `html.customData` at it for VS Code / Volar) and `dist/web-types.json` (picked up automatically by the JetBrains IDEs). Both are generated from the custom-elements manifests, and cover plain HTML, Angular templates and Vue SFCs.\n\n## Server-side rendering and static HTML\n\n- Components must not touch `document`/`window` at module scope; the c2 components guard with `isServer`.\n- Without SSR of the shadow DOM, hide unregistered tags until they upgrade: `c2-modal:not(:defined) { display: none }` (dialogs, lists) or `visibility: hidden` (layout-stable chrome).\n- Server-rendered markup only carries attributes, so spell camelCase properties as their kebab-case attribute (`row-key`); see the React section for why the camelCase spelling is lost on the way.\n- Theme CSS is plain CSS; load it in the document head so the first paint is themed.\n- \"Lit is in dev mode. Not recommended for production!\" in a dev server (Next.js, Vite) is expected: Lit publishes a `development` export condition with extra checks and warnings, and dev servers resolve it. A production build resolves the default condition and the message is gone; nothing to configure.\n"
50894
51742
  }
50895
51743
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@c2n/mcp",
3
- "version": "0.0.10",
3
+ "version": "0.0.12",
4
4
  "description": "MCP server exposing the c2n web components (API, examples, presets, theme tokens, variant generation) to AI agents",
5
5
  "type": "module",
6
6
  "bin": {
@@ -101,5 +101,5 @@
101
101
  "@c2n/config": "*",
102
102
  "custom-elements-manifest": "2.1.0"
103
103
  },
104
- "gitHead": "8d57710b3345fcb01cdb4cb15d2d43ba8bf21642"
104
+ "gitHead": "43e38b42ac221ffeef99a773c42dd3356961d26a"
105
105
  }