@openwarelabs/ui 0.11.0 → 0.12.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.
Files changed (43) hide show
  1. package/dist/components/AppShell/AppShell.context.d.cts +21 -0
  2. package/dist/components/AppShell/AppShell.context.d.ts +21 -0
  3. package/dist/components/AppShell/AppShell.d.cts +17 -0
  4. package/dist/components/AppShell/AppShell.d.ts +17 -0
  5. package/dist/components/AppShell/AppShell.types.d.cts +46 -0
  6. package/dist/components/AppShell/AppShell.types.d.ts +46 -0
  7. package/dist/components/Chart/BarChart.d.cts +6 -0
  8. package/dist/components/Chart/BarChart.d.ts +6 -0
  9. package/dist/components/Chart/Cartesian.d.cts +8 -0
  10. package/dist/components/Chart/Cartesian.d.ts +8 -0
  11. package/dist/components/Chart/Chart.d.cts +5 -0
  12. package/dist/components/Chart/Chart.d.ts +5 -0
  13. package/dist/components/Chart/Chart.types.d.cts +83 -0
  14. package/dist/components/Chart/Chart.types.d.ts +83 -0
  15. package/dist/components/Chart/ChartParts.d.cts +16 -0
  16. package/dist/components/Chart/ChartParts.d.ts +16 -0
  17. package/dist/components/Chart/DonutChart.d.cts +6 -0
  18. package/dist/components/Chart/DonutChart.d.ts +6 -0
  19. package/dist/components/Chart/LineChart.d.cts +6 -0
  20. package/dist/components/Chart/LineChart.d.ts +6 -0
  21. package/dist/components/Chart/Sparkline.d.cts +6 -0
  22. package/dist/components/Chart/Sparkline.d.ts +6 -0
  23. package/dist/components/Chart/chartUtils.d.cts +13 -0
  24. package/dist/components/Chart/chartUtils.d.ts +13 -0
  25. package/dist/components/NavList/NavList.d.cts +6 -24
  26. package/dist/components/NavList/NavList.d.ts +6 -24
  27. package/dist/components/NavList/NavList.types.d.cts +23 -0
  28. package/dist/components/NavList/NavList.types.d.ts +23 -0
  29. package/dist/components.css +516 -4
  30. package/dist/icons.d.cts +3 -0
  31. package/dist/icons.d.ts +3 -0
  32. package/dist/index.cjs +1299 -729
  33. package/dist/index.cjs.map +4 -4
  34. package/dist/index.d.cts +4 -0
  35. package/dist/index.d.ts +4 -0
  36. package/dist/index.js +1281 -711
  37. package/dist/index.js.map +4 -4
  38. package/dist/openware-ui.iife.js +8 -8
  39. package/dist/styles.css +546 -4
  40. package/dist/tailwind.css +10 -0
  41. package/dist/tokens.css +30 -0
  42. package/dist/tokens.json +80 -0
  43. package/package.json +1 -1
@@ -1999,7 +1999,8 @@
1999
1999
 
2000
2000
  .ow-slider__control {
2001
2001
  position: relative;
2002
- height: 20px;
2002
+ /* 24px tall so each handle's input is a big enough target to tap (WCAG 2.2 target size). */
2003
+ height: 24px;
2003
2004
  }
2004
2005
 
2005
2006
  /* The track runs between the thumb's centre at each end (9px in), so the fill meets the thumb exactly. */
@@ -2045,12 +2046,12 @@
2045
2046
  }
2046
2047
 
2047
2048
  .ow-slider__input::-webkit-slider-runnable-track {
2048
- height: 20px;
2049
+ height: 24px;
2049
2050
  background: transparent;
2050
2051
  }
2051
2052
 
2052
2053
  .ow-slider__input::-moz-range-track {
2053
- height: 20px;
2054
+ height: 24px;
2054
2055
  background: transparent;
2055
2056
  }
2056
2057
 
@@ -2058,7 +2059,7 @@
2058
2059
  box-sizing: border-box;
2059
2060
  width: 18px;
2060
2061
  height: 18px;
2061
- margin-top: 1px;
2062
+ margin-top: 3px;
2062
2063
  appearance: none;
2063
2064
  border: 1px solid var(--ow-border-strong);
2064
2065
  border-radius: 50%;
@@ -5829,6 +5830,283 @@
5829
5830
  transform: translate(-50%, -50%);
5830
5831
  }
5831
5832
 
5833
+ /* components/Chart/Chart.css */
5834
+ /* Charts: thin marks in the chart palette (--ow-chart-1 to 8), hairline grids, text in text colours, never the series'. */
5835
+
5836
+ .ow-chart {
5837
+ display: grid;
5838
+ min-width: 0;
5839
+ gap: var(--ow-space-lg);
5840
+ margin: 0;
5841
+ }
5842
+
5843
+ .ow-chart__legend {
5844
+ display: flex;
5845
+ flex-wrap: wrap;
5846
+ gap: var(--ow-space-xs) var(--ow-space-2xl);
5847
+ margin: 0;
5848
+ padding: 0;
5849
+ list-style: none;
5850
+ }
5851
+
5852
+ .ow-chart__legend-item {
5853
+ display: inline-flex;
5854
+ align-items: center;
5855
+ gap: var(--ow-space-sm);
5856
+ color: var(--ow-text-soft);
5857
+ font-size: 13px;
5858
+ }
5859
+
5860
+ .ow-chart__legend-value {
5861
+ color: var(--ow-text-muted);
5862
+ font-variant-numeric: tabular-nums;
5863
+ }
5864
+
5865
+ .ow-chart__key {
5866
+ flex-shrink: 0;
5867
+ }
5868
+
5869
+ .ow-chart__key--line {
5870
+ width: 14px;
5871
+ height: 2px;
5872
+ border-radius: 1px;
5873
+ }
5874
+
5875
+ .ow-chart__key--square {
5876
+ width: 10px;
5877
+ height: 10px;
5878
+ border-radius: 3px;
5879
+ }
5880
+
5881
+ .ow-chart__plot {
5882
+ position: relative;
5883
+ min-width: 0;
5884
+ border-radius: var(--ow-radius-md);
5885
+ touch-action: pan-y;
5886
+ }
5887
+
5888
+ .ow-chart__plot:focus-visible,
5889
+ .ow-chart__donut:focus-visible {
5890
+ outline: 2px solid var(--ow-focus-ring);
5891
+ outline-offset: 4px;
5892
+ }
5893
+
5894
+ .ow-chart__svg {
5895
+ display: block;
5896
+ overflow: visible;
5897
+ }
5898
+
5899
+ .ow-chart__grid {
5900
+ stroke: var(--ow-chart-grid);
5901
+ stroke-width: 1px;
5902
+ shape-rendering: crispEdges;
5903
+ }
5904
+
5905
+ .ow-chart__baseline {
5906
+ stroke: var(--ow-chart-axis);
5907
+ stroke-width: 1px;
5908
+ shape-rendering: crispEdges;
5909
+ }
5910
+
5911
+ .ow-chart__tick {
5912
+ fill: var(--ow-text-muted);
5913
+ font-family: var(--ow-font-sans);
5914
+ font-size: 11.5px;
5915
+ font-variant-numeric: tabular-nums;
5916
+ }
5917
+
5918
+ .ow-chart__line {
5919
+ fill: none;
5920
+ stroke-width: 2px;
5921
+ stroke-linecap: round;
5922
+ stroke-linejoin: round;
5923
+ }
5924
+
5925
+ .ow-chart__area {
5926
+ fill-opacity: 0.1;
5927
+ }
5928
+
5929
+ .ow-chart__point {
5930
+ stroke: var(--ow-surface);
5931
+ stroke-width: 2px;
5932
+ }
5933
+
5934
+ .ow-chart__crosshair {
5935
+ stroke: var(--ow-chart-axis);
5936
+ stroke-width: 1px;
5937
+ shape-rendering: crispEdges;
5938
+ }
5939
+
5940
+ .ow-chart__band {
5941
+ fill: var(--ow-surface-muted);
5942
+ }
5943
+
5944
+ .ow-chart__hit {
5945
+ fill: transparent;
5946
+ cursor: crosshair;
5947
+ }
5948
+
5949
+ .ow-chart--bar .ow-chart__hit {
5950
+ cursor: default;
5951
+ }
5952
+
5953
+ /* The readout for the hovered or focused point. */
5954
+ .ow-chart__readout {
5955
+ position: absolute;
5956
+ top: 4px;
5957
+ z-index: 1;
5958
+ display: grid;
5959
+ min-width: 140px;
5960
+ gap: 6px;
5961
+ border: 1px solid var(--ow-border);
5962
+ border-radius: var(--ow-radius-lg);
5963
+ background: var(--ow-surface);
5964
+ box-shadow: var(--ow-shadow-menu);
5965
+ padding: 9px 12px 10px;
5966
+ pointer-events: none;
5967
+ }
5968
+
5969
+ .ow-chart__readout-title {
5970
+ color: var(--ow-text-muted);
5971
+ font-size: 12px;
5972
+ }
5973
+
5974
+ .ow-chart__readout-row {
5975
+ display: flex;
5976
+ align-items: center;
5977
+ gap: 8px;
5978
+ color: var(--ow-text-muted);
5979
+ font-size: 12.5px;
5980
+ white-space: nowrap;
5981
+ }
5982
+
5983
+ .ow-chart__readout-label {
5984
+ flex: 1;
5985
+ }
5986
+
5987
+ .ow-chart__readout-row strong {
5988
+ margin-left: 12px;
5989
+ color: var(--ow-text);
5990
+ font-size: 13.5px;
5991
+ font-weight: var(--ow-weight-emphasis);
5992
+ font-variant-numeric: tabular-nums;
5993
+ }
5994
+
5995
+ /* Donut: the ring with the total in its middle, the legend beside it. */
5996
+ .ow-chart--donut {
5997
+ display: flex;
5998
+ flex-wrap: wrap;
5999
+ align-items: center;
6000
+ gap: var(--ow-space-4xl) 32px;
6001
+ }
6002
+
6003
+ .ow-chart--donut .ow-chart__legend {
6004
+ display: grid;
6005
+ gap: var(--ow-space-sm);
6006
+ }
6007
+
6008
+ .ow-chart__donut {
6009
+ position: relative;
6010
+ flex-shrink: 0;
6011
+ border-radius: 50%;
6012
+ }
6013
+
6014
+ .ow-chart__donut svg {
6015
+ display: block;
6016
+ }
6017
+
6018
+ .ow-chart__slice {
6019
+ transition: opacity var(--ow-duration-base) var(--ow-ease-standard);
6020
+ }
6021
+
6022
+ .ow-chart__slice--dim {
6023
+ opacity: 0.35;
6024
+ }
6025
+
6026
+ .ow-chart__empty {
6027
+ fill: none;
6028
+ stroke: var(--ow-meter-track);
6029
+ }
6030
+
6031
+ .ow-chart__center {
6032
+ position: absolute;
6033
+ inset: 0;
6034
+ display: grid;
6035
+ place-content: center;
6036
+ gap: 2px;
6037
+ padding: 0 22%;
6038
+ text-align: center;
6039
+ pointer-events: none;
6040
+ }
6041
+
6042
+ .ow-chart__center-value {
6043
+ color: var(--ow-text);
6044
+ font-size: 20px;
6045
+ font-weight: var(--ow-weight-emphasis);
6046
+ font-variant-numeric: tabular-nums;
6047
+ letter-spacing: -0.01em;
6048
+ }
6049
+
6050
+ .ow-chart__center-label {
6051
+ overflow: hidden;
6052
+ color: var(--ow-text-muted);
6053
+ font-size: 12px;
6054
+ text-overflow: ellipsis;
6055
+ white-space: nowrap;
6056
+ }
6057
+
6058
+ /* Sparkline */
6059
+ .ow-sparkline {
6060
+ position: relative;
6061
+ display: inline-block;
6062
+ flex-shrink: 0;
6063
+ vertical-align: middle;
6064
+ }
6065
+
6066
+ .ow-sparkline svg {
6067
+ display: block;
6068
+ width: 100%;
6069
+ height: 100%;
6070
+ overflow: visible;
6071
+ }
6072
+
6073
+ .ow-sparkline__area {
6074
+ fill: var(--ow-sparkline-color);
6075
+ fill-opacity: 0.1;
6076
+ }
6077
+
6078
+ .ow-sparkline__line {
6079
+ fill: none;
6080
+ stroke: var(--ow-sparkline-color);
6081
+ stroke-width: 1.75px;
6082
+ stroke-linejoin: round;
6083
+ stroke-linecap: round;
6084
+ }
6085
+
6086
+ .ow-sparkline__end {
6087
+ position: absolute;
6088
+ width: 8px;
6089
+ height: 8px;
6090
+ box-sizing: border-box;
6091
+ border: 2px solid var(--ow-surface);
6092
+ border-radius: 50%;
6093
+ background: var(--ow-sparkline-color);
6094
+ transform: translate(-50%, -50%);
6095
+ }
6096
+
6097
+ @media (prefers-reduced-motion: reduce) {
6098
+ .ow-chart__slice {
6099
+ transition: none;
6100
+ }
6101
+ }
6102
+
6103
+ @media (forced-colors: active) {
6104
+ .ow-chart__line,
6105
+ .ow-sparkline__line {
6106
+ stroke: CanvasText;
6107
+ }
6108
+ }
6109
+
5832
6110
  /* components/FileTree/FileTree.css */
5833
6111
  /* FileTree: a project structure explorer. Monospace names, hairline guides, a tinted selected file. */
5834
6112
  .ow-tree,
@@ -6137,6 +6415,240 @@
6137
6415
  font-weight: var(--ow-weight-regular);
6138
6416
  }
6139
6417
 
6418
+ /* components/AppShell/AppShell.css */
6419
+ /* AppShell: a sidebar down the left and the page beside it. It measures its own width (a container query), so it
6420
+ folds into a drawer under its breakpoint (900px by default) whether it fills the window or sits in a smaller frame. */
6421
+
6422
+ .ow-app-shell {
6423
+ --ow-app-shell-height: 100dvh;
6424
+ --ow-sidebar-width: 248px;
6425
+ --ow-sidebar-collapsed-width: 56px;
6426
+ container: ow-app-shell / inline-size;
6427
+ background: var(--ow-canvas);
6428
+ color: var(--ow-text);
6429
+ }
6430
+
6431
+ .ow-app-shell__frame {
6432
+ display: grid;
6433
+ grid-template-columns: var(--ow-sidebar-width) minmax(0, 1fr);
6434
+ min-height: var(--ow-app-shell-height);
6435
+ transition: grid-template-columns var(--ow-duration-base) var(--ow-ease-standard);
6436
+ }
6437
+
6438
+ .ow-app-shell--collapsed .ow-app-shell__frame {
6439
+ grid-template-columns: var(--ow-sidebar-collapsed-width) minmax(0, 1fr);
6440
+ }
6441
+
6442
+ .ow-app-shell__sidebar {
6443
+ position: sticky;
6444
+ top: 0;
6445
+ box-sizing: border-box;
6446
+ height: var(--ow-app-shell-height);
6447
+ min-width: 0;
6448
+ overflow: hidden;
6449
+ }
6450
+
6451
+ .ow-app-shell--flat .ow-app-shell__sidebar {
6452
+ border-right: 1px solid var(--ow-border);
6453
+ }
6454
+
6455
+ /* The sidebar's three parts: the header and footer stay put, the content between them scrolls. */
6456
+ .ow-sidebar {
6457
+ display: flex;
6458
+ box-sizing: border-box;
6459
+ height: 100%;
6460
+ flex-direction: column;
6461
+ gap: var(--ow-space-lg);
6462
+ padding: 10px 12px 12px;
6463
+ }
6464
+
6465
+ .ow-sidebar--drawer {
6466
+ height: auto;
6467
+ min-height: 100%;
6468
+ padding: 0;
6469
+ }
6470
+
6471
+ .ow-sidebar__header,
6472
+ .ow-sidebar__footer {
6473
+ display: flex;
6474
+ flex-direction: column;
6475
+ flex-shrink: 0;
6476
+ gap: var(--ow-space-sm);
6477
+ }
6478
+
6479
+ .ow-sidebar__content {
6480
+ display: flex;
6481
+ min-height: 0;
6482
+ flex: 1;
6483
+ flex-direction: column;
6484
+ gap: var(--ow-space-3xl);
6485
+ overflow-y: auto;
6486
+ /* Room for the items' focus rings, which the scroll area would otherwise clip. */
6487
+ margin-inline: -4px;
6488
+ padding: 2px 4px;
6489
+ }
6490
+
6491
+ .ow-sidebar--drawer .ow-sidebar__content {
6492
+ overflow: visible;
6493
+ }
6494
+
6495
+ .ow-sidebar__footer {
6496
+ margin-top: auto;
6497
+ }
6498
+
6499
+ .ow-sidebar__toggle {
6500
+ align-self: flex-start;
6501
+ }
6502
+
6503
+ /* Inside a NavList each tooltip wraps its item: let the item keep the full width. */
6504
+ .ow-sidebar .ow-nav > .ow-tooltip {
6505
+ display: grid;
6506
+ }
6507
+
6508
+ /* Folded: only the icons show; the labels stay for screen readers and come back as tooltips. */
6509
+ .ow-app-shell--collapsed .ow-app-shell__sidebar .ow-sidebar {
6510
+ padding-inline: 8px;
6511
+ }
6512
+
6513
+ .ow-app-shell--collapsed .ow-app-shell__sidebar .ow-nav__item {
6514
+ justify-content: center;
6515
+ padding-inline: 0;
6516
+ }
6517
+
6518
+ .ow-app-shell--collapsed .ow-app-shell__sidebar .ow-nav__label {
6519
+ position: absolute;
6520
+ width: 1px;
6521
+ height: 1px;
6522
+ overflow: hidden;
6523
+ clip-path: inset(50%);
6524
+ white-space: nowrap;
6525
+ }
6526
+
6527
+ .ow-app-shell--collapsed .ow-app-shell__sidebar .ow-nav__end {
6528
+ display: none;
6529
+ }
6530
+
6531
+ /* A group's heading becomes a short rule, so the groups still read as groups. */
6532
+ .ow-app-shell--collapsed .ow-app-shell__sidebar .ow-nav__heading {
6533
+ height: 1px;
6534
+ overflow: hidden;
6535
+ margin: 4px 8px;
6536
+ background: var(--ow-border);
6537
+ padding: 0;
6538
+ color: transparent;
6539
+ }
6540
+
6541
+ .ow-app-shell--collapsed .ow-sidebar__toggle {
6542
+ align-self: center;
6543
+ }
6544
+
6545
+ .ow-app-shell__body {
6546
+ display: flex;
6547
+ min-width: 0;
6548
+ flex-direction: column;
6549
+ }
6550
+
6551
+ .ow-app-shell__main {
6552
+ display: flex;
6553
+ min-width: 0;
6554
+ flex: 1;
6555
+ flex-direction: column;
6556
+ }
6557
+
6558
+ .ow-app-shell--inset .ow-app-shell__main {
6559
+ margin: 8px 8px 8px 0;
6560
+ border: 1px solid var(--ow-border);
6561
+ border-radius: var(--ow-radius-panel);
6562
+ background: var(--ow-surface);
6563
+ }
6564
+
6565
+ .ow-app-shell--flat .ow-app-shell__body {
6566
+ background: var(--ow-surface);
6567
+ }
6568
+
6569
+ /* On narrow screens the sidebar folds into a drawer behind this bar. */
6570
+ .ow-app-shell__topbar {
6571
+ display: none;
6572
+ height: 52px;
6573
+ flex-shrink: 0;
6574
+ align-items: center;
6575
+ gap: var(--ow-space-sm);
6576
+ padding: 0 6px;
6577
+ }
6578
+
6579
+ .ow-app-shell__topbar-start {
6580
+ display: flex;
6581
+ min-width: 0;
6582
+ flex: 1;
6583
+ align-items: center;
6584
+ gap: 9px;
6585
+ }
6586
+
6587
+ .ow-app-shell__topbar-end {
6588
+ display: flex;
6589
+ align-items: center;
6590
+ gap: var(--ow-space-2xs);
6591
+ }
6592
+
6593
+ .ow-app-shell--flat .ow-app-shell__topbar {
6594
+ border-bottom: 1px solid var(--ow-border);
6595
+ }
6596
+
6597
+ /* Where the sidebar folds into the drawer: the breakpoint prop. */
6598
+ @container ow-app-shell (max-width: 559px) {
6599
+ .ow-app-shell--sm .ow-app-shell__frame,
6600
+ .ow-app-shell--sm.ow-app-shell--collapsed .ow-app-shell__frame {
6601
+ grid-template-columns: minmax(0, 1fr);
6602
+ }
6603
+ .ow-app-shell--sm .ow-app-shell__sidebar {
6604
+ display: none;
6605
+ }
6606
+ .ow-app-shell--sm .ow-app-shell__topbar {
6607
+ display: flex;
6608
+ }
6609
+ .ow-app-shell--sm.ow-app-shell--inset .ow-app-shell__main {
6610
+ margin: 0 8px 8px;
6611
+ }
6612
+ }
6613
+
6614
+ @container ow-app-shell (max-width: 899px) {
6615
+ .ow-app-shell--md .ow-app-shell__frame,
6616
+ .ow-app-shell--md.ow-app-shell--collapsed .ow-app-shell__frame {
6617
+ grid-template-columns: minmax(0, 1fr);
6618
+ }
6619
+ .ow-app-shell--md .ow-app-shell__sidebar {
6620
+ display: none;
6621
+ }
6622
+ .ow-app-shell--md .ow-app-shell__topbar {
6623
+ display: flex;
6624
+ }
6625
+ .ow-app-shell--md.ow-app-shell--inset .ow-app-shell__main {
6626
+ margin: 0 8px 8px;
6627
+ }
6628
+ }
6629
+
6630
+ @container ow-app-shell (max-width: 1199px) {
6631
+ .ow-app-shell--lg .ow-app-shell__frame,
6632
+ .ow-app-shell--lg.ow-app-shell--collapsed .ow-app-shell__frame {
6633
+ grid-template-columns: minmax(0, 1fr);
6634
+ }
6635
+ .ow-app-shell--lg .ow-app-shell__sidebar {
6636
+ display: none;
6637
+ }
6638
+ .ow-app-shell--lg .ow-app-shell__topbar {
6639
+ display: flex;
6640
+ }
6641
+ .ow-app-shell--lg.ow-app-shell--inset .ow-app-shell__main {
6642
+ margin: 0 8px 8px;
6643
+ }
6644
+ }
6645
+
6646
+ @media (prefers-reduced-motion: reduce) {
6647
+ .ow-app-shell__frame {
6648
+ transition: none;
6649
+ }
6650
+ }
6651
+
6140
6652
  /* components/Layout/Layout.css */
6141
6653
  /* Stack, Separator and ScrollShadow. */
6142
6654
  .ow-stack {
package/dist/icons.d.cts CHANGED
@@ -31,3 +31,6 @@ export declare const ArrowDownIcon: ({ size, strokeWidth, ...props }: IconProps)
31
31
  export declare const ChevronsUpDownIcon: ({ size, strokeWidth, ...props }: IconProps) => import("react").JSX.Element;
32
32
  export declare const InboxIcon: ({ size, strokeWidth, ...props }: IconProps) => import("react").JSX.Element;
33
33
  export declare const EllipsisIcon: ({ size, strokeWidth, ...props }: IconProps) => import("react").JSX.Element;
34
+ export declare const MenuIcon: ({ size, strokeWidth, ...props }: IconProps) => import("react").JSX.Element;
35
+ export declare const PanelLeftOpenIcon: ({ size, strokeWidth, ...props }: IconProps) => import("react").JSX.Element;
36
+ export declare const PanelLeftCloseIcon: ({ size, strokeWidth, ...props }: IconProps) => import("react").JSX.Element;
package/dist/icons.d.ts CHANGED
@@ -31,3 +31,6 @@ export declare const ArrowDownIcon: ({ size, strokeWidth, ...props }: IconProps)
31
31
  export declare const ChevronsUpDownIcon: ({ size, strokeWidth, ...props }: IconProps) => import("react").JSX.Element;
32
32
  export declare const InboxIcon: ({ size, strokeWidth, ...props }: IconProps) => import("react").JSX.Element;
33
33
  export declare const EllipsisIcon: ({ size, strokeWidth, ...props }: IconProps) => import("react").JSX.Element;
34
+ export declare const MenuIcon: ({ size, strokeWidth, ...props }: IconProps) => import("react").JSX.Element;
35
+ export declare const PanelLeftOpenIcon: ({ size, strokeWidth, ...props }: IconProps) => import("react").JSX.Element;
36
+ export declare const PanelLeftCloseIcon: ({ size, strokeWidth, ...props }: IconProps) => import("react").JSX.Element;