coveragebook_components 0.7.8 → 0.7.10

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 (38) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/build/coco/app.css +70 -17
  3. data/app/assets/build/coco/app.js +54 -4
  4. data/app/assets/build/coco/book.css +30 -9
  5. data/app/assets/build/coco/book.js +24 -2
  6. data/app/assets/css/base/base.css +12 -0
  7. data/app/assets/css/base/components/coco.css +0 -3
  8. data/app/assets/js/app/setup.js +22 -0
  9. data/app/assets/js/app.js +2 -0
  10. data/app/assets/js/helpers/location.js +9 -0
  11. data/app/assets/js/libs/tippy/index.js +7 -2
  12. data/app/components/coco/app/elements/alert/alert.html.erb +18 -3
  13. data/app/components/coco/app/elements/alert/alert.rb +6 -6
  14. data/app/components/coco/app/elements/button/button.css +29 -5
  15. data/app/components/coco/app/elements/button/button.rb +21 -0
  16. data/app/components/coco/app/elements/button_to/button_to.css +5 -1
  17. data/app/components/coco/app/elements/button_to/button_to.rb +8 -1
  18. data/app/components/coco/app/elements/link/link.rb +18 -0
  19. data/app/components/coco/app/elements/menu/menu.css +4 -0
  20. data/app/components/coco/app/elements/menu_button/menu_button.html.erb +6 -0
  21. data/app/components/coco/app/elements/menu_button/menu_button.rb +8 -9
  22. data/app/components/coco/app/elements/notice/notice.rb +2 -2
  23. data/app/components/coco/base/button/button.css +1 -1
  24. data/app/components/coco/base/icon/icon.css +6 -2
  25. data/app/components/coco/base/icon/icon.rb +1 -1
  26. data/app/components/coco/base/modal/modal.css +2 -1
  27. data/app/components/coco/base/modal/modal.js +2 -0
  28. data/app/components/coco/base/modal_lightbox/modal_lightbox.js +2 -2
  29. data/app/components/coco/base/placeholder/placeholder.css +15 -1
  30. data/app/components/coco/base/placeholder/placeholder.rb +2 -0
  31. data/app/components/coco/concerns/acts_as_button_group.rb +25 -12
  32. data/app/helpers/coco/app_helper.rb +11 -29
  33. data/app/helpers/coco/base_helper.rb +2 -0
  34. data/app/helpers/coco/url_helper.rb +5 -1
  35. data/config/tailwind.base.config.cjs +3 -0
  36. data/config/tokens.cjs +3 -0
  37. data/lib/coco.rb +1 -1
  38. metadata +4 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d300fed697f5a7f4c6efc0d61957f3cd3e4f89cf10907fc89ca8f1964f8d92bd
4
- data.tar.gz: dce48e1edfc753eee953bcf11dc66a960f0ba0a56f1728a488b92f65701a1744
3
+ metadata.gz: 0e49dab540e7bcff41a931205ffb5f404ad1f43b15fad059b58ed114647df93c
4
+ data.tar.gz: 60d3b1861955797ab13c58b58d20647df994534bfaae136134bf888703c994f2
5
5
  SHA512:
6
- metadata.gz: 9a32d872cd51dad95415230b33b3b38ba962229b0d292bc13d9a7847ead8cc71f793ea721c24910b92ecd229781cde7c3f395aa542dc98be2313da32bb104d1e
7
- data.tar.gz: 525b96dced44fda522bd3ecd7562f84608e2172c85372b705a170af1c42e1e01bf2309ff209470da33a2bbdcf84afd6e7b26958e518f17fb9fe82de873445b93
6
+ metadata.gz: aa861695cadd42ceb8dc4efa0adc6320b0a89747ec82b371c372c75f2a97c735da05e5ab4bfac03564daae497a5812f8381ccf92ecc8da02dbfa4fa094b66595
7
+ data.tar.gz: 5cc77f75ddb74d210d46fed6449707c627f77b0826eaf807643cec2daf98e11b082885191d882d837304233a11b11c25f28f52866dc87d8beceb6042d3e4c2f9
@@ -521,11 +521,16 @@ select{
521
521
  [type='file']:focus{
522
522
  outline: 1px solid ButtonText;
523
523
  outline: 1px auto -webkit-focus-ring-color}
524
+ :root {
525
+ --app-height: 100%;
526
+ }
527
+
524
528
  html{
525
529
  scroll-behavior: smooth;
526
530
  font-family: proxima-nova, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
527
531
  --tw-text-opacity: 1;
528
532
  color: rgb(17 24 39 / var(--tw-text-opacity))}
533
+
529
534
  @media (prefers-reduced-motion: no-preference){
530
535
 
531
536
  html{
@@ -685,10 +690,7 @@ select{
685
690
  [data-coco]{
686
691
  font-family: proxima-nova, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
687
692
  --tw-text-opacity: 1;
688
- color: rgb(17 24 39 / var(--tw-text-opacity));
689
-
690
- -webkit-font-smoothing: antialiased;
691
- -moz-osx-font-smoothing: grayscale}
693
+ color: rgb(17 24 39 / var(--tw-text-opacity))}
692
694
  [data-coco] h1,
693
695
  [data-coco] h2,
694
696
  [data-coco] h3,
@@ -767,6 +769,7 @@ select{
767
769
  order: 3}
768
770
  /* disabled */
769
771
  [data-coco].coco-button[data-disabled="true"] .button-element{
772
+ pointer-events: none;
770
773
  cursor: not-allowed}
771
774
  /* loading */
772
775
  @keyframes spin{
@@ -851,11 +854,14 @@ select{
851
854
  height: 1.5rem;
852
855
  width: 1.5rem}
853
856
  [data-coco][data-component="icon"][data-size="xl"]{
854
- height: 2.25rem;
855
- width: 2.25rem}
857
+ height: 2rem;
858
+ width: 2rem}
856
859
  [data-coco][data-component="icon"][data-size="xxl"]{
857
- height: 3rem;
858
- width: 3rem}
860
+ height: 2.5rem;
861
+ width: 2.5rem}
862
+ [data-coco][data-component="icon"][data-size="full"]{
863
+ height: 100%;
864
+ width: 100%}
859
865
  /* Motion */
860
866
  @keyframes spin{
861
867
 
@@ -907,7 +913,6 @@ select{
907
913
  position: relative;
908
914
  z-index: 10000;
909
915
  display: flex;
910
- min-height: 100vh;
911
916
  align-items: center;
912
917
  justify-content: center;
913
918
  padding: 0.5rem}
@@ -915,6 +920,9 @@ select{
915
920
 
916
921
  [data-coco][data-component="modal"] .modal-container{
917
922
  padding: 2rem}}
923
+ [data-coco][data-component="modal"] .modal-container {
924
+ min-height: var(--app-height);
925
+ }
918
926
  [data-coco][data-component="modal"] .modal-content{
919
927
  display: contents}
920
928
  /* transitions */
@@ -1129,13 +1137,19 @@ select{
1129
1137
  --tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color);
1130
1138
  box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow)}
1131
1139
  [data-coco][data-component="placeholder"]{
1140
+ padding: 1rem}
1141
+ [data-coco][data-component="placeholder"][data-boxed="true"]{
1132
1142
  border-width: 1px;
1133
1143
  border-style: dashed;
1134
1144
  --tw-border-opacity: 1;
1135
1145
  border-color: rgb(156 163 175 / var(--tw-border-opacity));
1136
1146
  --tw-bg-opacity: 1;
1137
- background-color: rgb(249 250 251 / var(--tw-bg-opacity));
1138
- padding: 1rem;
1147
+ background-color: rgb(249 250 251 / var(--tw-bg-opacity))}
1148
+ [data-coco][data-component="placeholder"][data-prose="true"] .placeholder-content > :not([hidden]) ~ :not([hidden]){
1149
+ --tw-space-y-reverse: 0;
1150
+ margin-top: calc(0.75rem * calc(1 - var(--tw-space-y-reverse)));
1151
+ margin-bottom: calc(0.75rem * var(--tw-space-y-reverse))}
1152
+ [data-coco][data-component="placeholder"][data-prose="false"]{
1139
1153
  text-align: center}
1140
1154
  [data-coco][data-component="placeholder"][data-size="full"]{
1141
1155
  height: 100%;
@@ -1792,7 +1806,9 @@ select{
1792
1806
  --tw-bg-opacity: 1;
1793
1807
  background-color: rgb(26 136 113 / var(--tw-bg-opacity));
1794
1808
  --tw-text-opacity: 1;
1795
- color: rgb(255 255 255 / var(--tw-text-opacity))}
1809
+ color: rgb(255 255 255 / var(--tw-text-opacity));
1810
+ -webkit-font-smoothing: antialiased;
1811
+ -moz-osx-font-smoothing: grayscale}
1796
1812
  [data-coco][data-component="app-button"][data-theme="primary"]:hover,
1797
1813
  [data-coco][data-component="app-button"][data-theme="positive"]:hover{
1798
1814
  --tw-bg-opacity: 1;
@@ -1907,7 +1923,9 @@ select{
1907
1923
  --tw-bg-opacity: 1;
1908
1924
  background-color: rgb(220 38 38 / var(--tw-bg-opacity));
1909
1925
  --tw-text-opacity: 1;
1910
- color: rgb(255 255 255 / var(--tw-text-opacity))}
1926
+ color: rgb(255 255 255 / var(--tw-text-opacity));
1927
+ -webkit-font-smoothing: antialiased;
1928
+ -moz-osx-font-smoothing: grayscale}
1911
1929
  [data-coco][data-component="app-button"][data-theme="negative"]:hover{
1912
1930
  --tw-bg-opacity: 1;
1913
1931
  background-color: rgb(185 28 28 / var(--tw-bg-opacity))}
@@ -1951,7 +1969,9 @@ select{
1951
1969
  --tw-bg-opacity: 1;
1952
1970
  background-color: rgb(245 158 11 / var(--tw-bg-opacity));
1953
1971
  --tw-text-opacity: 1;
1954
- color: rgb(255 255 255 / var(--tw-text-opacity))}
1972
+ color: rgb(255 255 255 / var(--tw-text-opacity));
1973
+ -webkit-font-smoothing: antialiased;
1974
+ -moz-osx-font-smoothing: grayscale}
1955
1975
  [data-coco][data-component="app-button"][data-theme="warning"]:hover{
1956
1976
  --tw-bg-opacity: 1;
1957
1977
  background-color: rgb(180 83 9 / var(--tw-bg-opacity))}
@@ -1995,7 +2015,9 @@ select{
1995
2015
  --tw-bg-opacity: 1;
1996
2016
  background-color: rgb(2 132 199 / var(--tw-bg-opacity));
1997
2017
  --tw-text-opacity: 1;
1998
- color: rgb(255 255 255 / var(--tw-text-opacity))}
2018
+ color: rgb(255 255 255 / var(--tw-text-opacity));
2019
+ -webkit-font-smoothing: antialiased;
2020
+ -moz-osx-font-smoothing: grayscale}
1999
2021
  [data-coco][data-component="app-button"][data-theme="info"]:hover{
2000
2022
  --tw-bg-opacity: 1;
2001
2023
  background-color: rgb(3 105 161 / var(--tw-bg-opacity))}
@@ -2039,7 +2061,9 @@ select{
2039
2061
  --tw-bg-opacity: 1;
2040
2062
  background-color: rgb(17 24 39 / var(--tw-bg-opacity));
2041
2063
  --tw-text-opacity: 1;
2042
- color: rgb(255 255 255 / var(--tw-text-opacity))}
2064
+ color: rgb(255 255 255 / var(--tw-text-opacity));
2065
+ -webkit-font-smoothing: antialiased;
2066
+ -moz-osx-font-smoothing: grayscale}
2043
2067
  [data-coco][data-component="app-button"][data-theme="neutral-dark"]:hover{
2044
2068
  --tw-bg-opacity: 1;
2045
2069
  background-color: rgb(55 65 81 / var(--tw-bg-opacity))}
@@ -2077,6 +2101,28 @@ select{
2077
2101
  background-color: rgb(255 255 255 / var(--tw-bg-opacity))}
2078
2102
  [data-coco][data-component="app-button"][data-theme="neutral-light"][data-disabled="true"] .button-inner{
2079
2103
  opacity: 0.4}
2104
+ [data-coco][data-component="app-button"][data-theme="text-neutral-light"]{
2105
+ background-color: transparent;
2106
+ --tw-text-opacity: 1;
2107
+ color: rgb(255 255 255 / var(--tw-text-opacity));
2108
+ -webkit-font-smoothing: antialiased;
2109
+ -moz-osx-font-smoothing: grayscale}
2110
+ [data-coco][data-component="app-button"][data-theme="text-neutral-light"]:hover{
2111
+ background-color: rgb(255 255 255 / 0.1)}
2112
+ [data-coco][data-component="app-button"][data-theme="text-neutral-light"][data-state="active"]{
2113
+ background-color: rgb(255 255 255 / 0.1)}
2114
+ [data-coco][data-component="app-button"][data-theme="text-neutral-light"][data-disabled="true"]{
2115
+ opacity: 0.3}
2116
+ [data-coco][data-component="app-button"][data-theme="text-neutral-dark"]{
2117
+ background-color: transparent;
2118
+ --tw-text-opacity: 1;
2119
+ color: rgb(17 24 39 / var(--tw-text-opacity))}
2120
+ [data-coco][data-component="app-button"][data-theme="text-neutral-dark"]:hover{
2121
+ background-color: rgb(17 24 39 / 0.1)}
2122
+ [data-coco][data-component="app-button"][data-theme="text-neutral-dark"][data-state="active"]{
2123
+ background-color: rgb(17 24 39 / 0.1)}
2124
+ [data-coco][data-component="app-button"][data-theme="text-neutral-dark"][data-disabled="true"]{
2125
+ opacity: 0.3}
2080
2126
  /* Responsive resizing */
2081
2127
  [data-coco][data-component="app-button"][data-size="sm"] .button-content{
2082
2128
  font-size: 14px;
@@ -2555,11 +2601,13 @@ select{
2555
2601
  --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);
2556
2602
  box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow)}
2557
2603
  [data-coco][data-component="app-button-to"]{
2558
- display: inline-flex;
2604
+ display: flex;
2559
2605
  width: -moz-max-content;
2560
2606
  width: max-content}
2561
2607
  [data-coco][data-component="app-button-to"] form{
2562
2608
  width: 100%}
2609
+ [data-coco][data-component="app-button-to"][data-fit="full"]{
2610
+ width: 100%}
2563
2611
  [data-coco][data-component="app-color-picker"]{
2564
2612
  --tw-bg-opacity: 1;
2565
2613
  background-color: rgb(249 250 251 / var(--tw-bg-opacity))}
@@ -3211,6 +3259,9 @@ select{
3211
3259
  text-align: left}
3212
3260
  [data-coco][data-component="app-menu"] .menu-item > [data-component="app-button"] .button-content, [data-coco][data-component="app-menu"] .menu-item > [data-component="app-button-to"] .button-content, [data-coco][data-component="app-menu"] .menu-item > [data-component="app-menu-button"] .button-content{
3213
3261
  font-weight: 400 !important}
3262
+ [data-coco][data-component="app-menu"] .menu-item .divider{
3263
+ margin-top: 0.375rem;
3264
+ margin-bottom: 0.375rem}
3214
3265
  [data-coco][data-component="app-menu"][data-size="sm"]{
3215
3266
  padding-top: 0.375rem;
3216
3267
  padding-bottom: 0.375rem}
@@ -3898,6 +3949,8 @@ select{
3898
3949
  position: static}
3899
3950
  .fixed{
3900
3951
  position: fixed}
3952
+ .\!block{
3953
+ display: block !important}
3901
3954
  .block{
3902
3955
  display: block}
3903
3956
  .flex{
@@ -6118,7 +6118,8 @@
6118
6118
  primary: {
6119
6119
  DEFAULT: colors.green[500],
6120
6120
  dark: colors.green[600],
6121
- inverse: colors.green[300]
6121
+ inverse: colors.green[300],
6122
+ "inverse-vivid": "#009979"
6122
6123
  },
6123
6124
  negative: {
6124
6125
  DEFAULT: colors.red[600],
@@ -6150,6 +6151,7 @@
6150
6151
  xl: "1200px",
6151
6152
  "2xl": "1400px",
6152
6153
  max: "1800px",
6154
+ "small-landscape": { raw: "(max-height: 760px) and (min-width: 576px)" },
6153
6155
  print: { raw: "print" }
6154
6156
  // Note: PDFs are rendered at a viewport width of 1280px
6155
6157
  };
@@ -6158,6 +6160,7 @@
6158
6160
  "para-sm": ["14px", "20px"],
6159
6161
  "para-md": ["16px", "24px"],
6160
6162
  "para-lg": ["18px", "27px"],
6163
+ "label-xxs": ["10px", "12px"],
6161
6164
  "label-xs": ["12px", "14px"],
6162
6165
  "label-sm": ["14px", "16px"],
6163
6166
  "label-md": ["16px", "20px"],
@@ -14032,7 +14035,7 @@
14032
14035
  var package_default = {
14033
14036
  name: "coveragebook-components",
14034
14037
  type: "module",
14035
- version: "0.7.8",
14038
+ version: "0.7.10",
14036
14039
  main: "index.js",
14037
14040
  repository: "git@github.com:coveragebook/coco.git",
14038
14041
  author: "Mark Perkins <mark@coveragebook.com>",
@@ -23006,6 +23009,27 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
23006
23009
  tippy.defaultProps = defaultProps;
23007
23010
  tippy.setDefaultProps = setDefaultProps;
23008
23011
  tippy.currentInput = currentInput;
23012
+ var hideAll = function hideAll2(_temp) {
23013
+ var _ref = _temp === void 0 ? {} : _temp, excludedReferenceOrInstance = _ref.exclude, duration = _ref.duration;
23014
+ mountedInstances.forEach(function(instance) {
23015
+ var isExcluded = false;
23016
+ if (excludedReferenceOrInstance) {
23017
+ isExcluded = isReferenceElement(excludedReferenceOrInstance) ? instance.reference === excludedReferenceOrInstance : instance.popper === excludedReferenceOrInstance.popper;
23018
+ }
23019
+ if (!isExcluded) {
23020
+ var originalDuration = instance.props.duration;
23021
+ instance.setProps({
23022
+ duration
23023
+ });
23024
+ instance.hide();
23025
+ if (!instance.state.isDestroyed) {
23026
+ instance.setProps({
23027
+ duration: originalDuration
23028
+ });
23029
+ }
23030
+ }
23031
+ });
23032
+ };
23009
23033
  var applyStylesModifier = Object.assign({}, applyStyles_default, {
23010
23034
  effect: function effect6(_ref) {
23011
23035
  var state = _ref.state;
@@ -23662,6 +23686,31 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
23662
23686
  module_default.plugin(notification_default);
23663
23687
  var alpine_default2 = module_default;
23664
23688
 
23689
+ // helpers/location.js
23690
+ function navigateTo(url, options = {}) {
23691
+ if (window.Turbo && options.turbo === true) {
23692
+ window.Turbo.visit(url, { action: options.action || "advance" });
23693
+ } else {
23694
+ location.assign(url);
23695
+ }
23696
+ }
23697
+
23698
+ // app/setup.js
23699
+ window.addEventListener("navigate", (event) => {
23700
+ const { url, turbo, action } = event.detail;
23701
+ if (url) {
23702
+ navigateTo(url, { turbo, action });
23703
+ }
23704
+ });
23705
+ function setAppHeightProperty() {
23706
+ document.documentElement.style.setProperty(
23707
+ "--app-height",
23708
+ `${window.innerHeight}px`
23709
+ );
23710
+ }
23711
+ window.addEventListener("resize", setAppHeightProperty);
23712
+ setAppHeightProperty();
23713
+
23665
23714
  // ../../components/coco/base/button/button.js
23666
23715
  var button_exports = {};
23667
23716
  __export(button_exports, {
@@ -23962,6 +24011,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
23962
24011
  },
23963
24012
  show() {
23964
24013
  this.open = true;
24014
+ hideAll();
23965
24015
  setTimeout(() => {
23966
24016
  this.$dispatch("modal:shown");
23967
24017
  }, 400);
@@ -24080,12 +24130,12 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
24080
24130
  },
24081
24131
  imageLoaded() {
24082
24132
  this.loaded = true;
24083
- this.$nextTick(() => {
24133
+ setTimeout(() => {
24084
24134
  const scrollTop = parseInt(this.img.dataset.scrollTop, 10);
24085
24135
  if (!isNaN(scrollTop) && scrollTop !== 0) {
24086
24136
  this.modal.scrollTo(scrollTop);
24087
24137
  }
24088
- });
24138
+ }, 200);
24089
24139
  },
24090
24140
  get img() {
24091
24141
  return this.$refs.media.querySelector("img");
@@ -542,12 +542,17 @@ select {
542
542
  outline: 1px solid ButtonText;
543
543
  outline: 1px auto -webkit-focus-ring-color;
544
544
  }
545
+ :root {
546
+ --app-height: 100%;
547
+ }
548
+
545
549
  html {
546
550
  scroll-behavior: smooth;
547
551
  font-family: proxima-nova, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
548
552
  --tw-text-opacity: 1;
549
553
  color: rgb(17 24 39 / var(--tw-text-opacity));
550
554
  }
555
+
551
556
  @media (prefers-reduced-motion: no-preference) {
552
557
 
553
558
  html {
@@ -723,9 +728,6 @@ select {
723
728
  font-family: proxima-nova, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
724
729
  --tw-text-opacity: 1;
725
730
  color: rgb(17 24 39 / var(--tw-text-opacity));
726
-
727
- -webkit-font-smoothing: antialiased;
728
- -moz-osx-font-smoothing: grayscale;
729
731
  }
730
732
  [data-coco] h1,
731
733
  [data-coco] h2,
@@ -797,6 +799,7 @@ select {
797
799
  }
798
800
  /* disabled */
799
801
  [data-coco].coco-button[data-disabled="true"] .button-element {
802
+ pointer-events: none;
800
803
  cursor: not-allowed;
801
804
  }
802
805
  /* loading */
@@ -904,12 +907,16 @@ select {
904
907
  width: 1.5rem;
905
908
  }
906
909
  [data-coco][data-component="icon"][data-size="xl"] {
907
- height: 2.25rem;
908
- width: 2.25rem;
910
+ height: 2rem;
911
+ width: 2rem;
909
912
  }
910
913
  [data-coco][data-component="icon"][data-size="xxl"] {
911
- height: 3rem;
912
- width: 3rem;
914
+ height: 2.5rem;
915
+ width: 2.5rem;
916
+ }
917
+ [data-coco][data-component="icon"][data-size="full"] {
918
+ height: 100%;
919
+ width: 100%;
913
920
  }
914
921
  /* Motion */
915
922
  @keyframes spin {
@@ -979,7 +986,6 @@ select {
979
986
  position: relative;
980
987
  z-index: 10000;
981
988
  display: flex;
982
- min-height: 100vh;
983
989
  align-items: center;
984
990
  justify-content: center;
985
991
  padding: 0.5rem;
@@ -990,6 +996,9 @@ select {
990
996
  padding: 2rem;
991
997
  }
992
998
  }
999
+ [data-coco][data-component="modal"] .modal-container {
1000
+ min-height: var(--app-height);
1001
+ }
993
1002
  [data-coco][data-component="modal"] .modal-content {
994
1003
  display: contents;
995
1004
  }
@@ -1252,13 +1261,22 @@ select {
1252
1261
  box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
1253
1262
  }
1254
1263
  [data-coco][data-component="placeholder"] {
1264
+ padding: 1rem;
1265
+ }
1266
+ [data-coco][data-component="placeholder"][data-boxed="true"] {
1255
1267
  border-width: 1px;
1256
1268
  border-style: dashed;
1257
1269
  --tw-border-opacity: 1;
1258
1270
  border-color: rgb(156 163 175 / var(--tw-border-opacity));
1259
1271
  --tw-bg-opacity: 1;
1260
1272
  background-color: rgb(249 250 251 / var(--tw-bg-opacity));
1261
- padding: 1rem;
1273
+ }
1274
+ [data-coco][data-component="placeholder"][data-prose="true"] .placeholder-content > :not([hidden]) ~ :not([hidden]) {
1275
+ --tw-space-y-reverse: 0;
1276
+ margin-top: calc(0.75rem * calc(1 - var(--tw-space-y-reverse)));
1277
+ margin-bottom: calc(0.75rem * var(--tw-space-y-reverse));
1278
+ }
1279
+ [data-coco][data-component="placeholder"][data-prose="false"] {
1262
1280
  text-align: center;
1263
1281
  }
1264
1282
  [data-coco][data-component="placeholder"][data-size="full"] {
@@ -1754,6 +1772,9 @@ select {
1754
1772
  .fixed {
1755
1773
  position: fixed;
1756
1774
  }
1775
+ .\!block {
1776
+ display: block !important;
1777
+ }
1757
1778
  .block {
1758
1779
  display: block;
1759
1780
  }
@@ -14395,6 +14395,27 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
14395
14395
  tippy.defaultProps = defaultProps;
14396
14396
  tippy.setDefaultProps = setDefaultProps;
14397
14397
  tippy.currentInput = currentInput;
14398
+ var hideAll = function hideAll2(_temp) {
14399
+ var _ref = _temp === void 0 ? {} : _temp, excludedReferenceOrInstance = _ref.exclude, duration = _ref.duration;
14400
+ mountedInstances.forEach(function(instance) {
14401
+ var isExcluded = false;
14402
+ if (excludedReferenceOrInstance) {
14403
+ isExcluded = isReferenceElement(excludedReferenceOrInstance) ? instance.reference === excludedReferenceOrInstance : instance.popper === excludedReferenceOrInstance.popper;
14404
+ }
14405
+ if (!isExcluded) {
14406
+ var originalDuration = instance.props.duration;
14407
+ instance.setProps({
14408
+ duration
14409
+ });
14410
+ instance.hide();
14411
+ if (!instance.state.isDestroyed) {
14412
+ instance.setProps({
14413
+ duration: originalDuration
14414
+ });
14415
+ }
14416
+ }
14417
+ });
14418
+ };
14398
14419
  var applyStylesModifier = Object.assign({}, applyStyles_default, {
14399
14420
  effect: function effect6(_ref) {
14400
14421
  var state = _ref.state;
@@ -15188,6 +15209,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
15188
15209
  },
15189
15210
  show() {
15190
15211
  this.open = true;
15212
+ hideAll();
15191
15213
  setTimeout(() => {
15192
15214
  this.$dispatch("modal:shown");
15193
15215
  }, 400);
@@ -15306,12 +15328,12 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
15306
15328
  },
15307
15329
  imageLoaded() {
15308
15330
  this.loaded = true;
15309
- this.$nextTick(() => {
15331
+ setTimeout(() => {
15310
15332
  const scrollTop = parseInt(this.img.dataset.scrollTop, 10);
15311
15333
  if (!isNaN(scrollTop) && scrollTop !== 0) {
15312
15334
  this.modal.scrollTo(scrollTop);
15313
15335
  }
15314
- });
15336
+ }, 200);
15315
15337
  },
15316
15338
  get img() {
15317
15339
  return this.$refs.media.querySelector("img");
@@ -10,10 +10,22 @@
10
10
  @import "./components/coco";
11
11
 
12
12
  @layer base {
13
+ :root {
14
+ --app-height: 100%;
15
+ }
16
+
13
17
  html {
14
18
  @apply font-body scroll-smooth motion-safe:scroll-auto text-content-dark-1;
15
19
  }
16
20
 
21
+ html.app-layout,
22
+ html.app-layout body {
23
+ width: 100vw;
24
+ height: 100vh;
25
+ height: var(—-app-height);
26
+ overflow: hidden;
27
+ }
28
+
17
29
  a {
18
30
  @apply text-current underline underline-offset-2;
19
31
  }
@@ -2,9 +2,6 @@
2
2
  [data-coco] {
3
3
  @apply text-content-dark-1 font-body;
4
4
 
5
- -webkit-font-smoothing: antialiased;
6
- -moz-osx-font-smoothing: grayscale;
7
-
8
5
  h1,
9
6
  h2,
10
7
  h3,
@@ -0,0 +1,22 @@
1
+ import { navigateTo } from "@helpers/location";
2
+
3
+ // Global JS navigation handler.
4
+ // Optionally uses Turbo for the page navigation.
5
+ window.addEventListener("navigate", (event) => {
6
+ const { url, turbo, action } = event.detail;
7
+ if (url) {
8
+ navigateTo(url, { turbo, action });
9
+ }
10
+ });
11
+
12
+ // Uodate the value of the `--app-height` css variable
13
+ // when the viewport size changes. To help work around the
14
+ // issues when using 100vh on mobile safari (https://medium.com/quick-code/100vh-problem-with-ios-safari-92ab23c852a8)
15
+ function setAppHeightProperty() {
16
+ document.documentElement.style.setProperty(
17
+ "--app-height",
18
+ `${window.innerHeight}px`
19
+ );
20
+ }
21
+ window.addEventListener("resize", setAppHeightProperty);
22
+ setAppHeightProperty();
data/app/assets/js/app.js CHANGED
@@ -5,6 +5,8 @@ console.info("Initializing Coco JS", packageJSON.version);
5
5
  import "container-query-polyfill";
6
6
  import Alpine from "@libs/alpine";
7
7
 
8
+ import "./app/setup";
9
+
8
10
  import "./base/components";
9
11
  import "./book/components";
10
12
  import "./app/components";
@@ -0,0 +1,9 @@
1
+ function navigateTo(url, options = {}) {
2
+ if (window.Turbo && options.turbo === true) {
3
+ window.Turbo.visit(url, { action: options.action || "advance" });
4
+ } else {
5
+ location.assign(url);
6
+ }
7
+ }
8
+
9
+ export { navigateTo };
@@ -1,4 +1,9 @@
1
- import tippy, { createSingleton, followCursor, roundArrow } from "tippy.js";
1
+ import tippy, {
2
+ createSingleton,
3
+ followCursor,
4
+ roundArrow,
5
+ hideAll,
6
+ } from "tippy.js";
2
7
  import hideOnEsc from "./plugins/hide_on_esc";
3
8
 
4
9
  tippy.setDefaultProps({
@@ -9,4 +14,4 @@ tippy.setDefaultProps({
9
14
  });
10
15
 
11
16
  export default tippy;
12
- export { tippy, createSingleton, hideOnEsc, followCursor };
17
+ export { tippy, createSingleton, hideOnEsc, followCursor, hideAll };
@@ -24,7 +24,12 @@
24
24
 
25
25
  <% if link? %>
26
26
  <div class="alert-link" data-role="link">
27
- <%= link %>
27
+ <%= helpers.coco_link(
28
+ *@link_data[:args],
29
+ **@link_data[:kwargs],
30
+ size: :sm,
31
+ &@link_data[:block]
32
+ ) %>
28
33
  </div>
29
34
  <% end %>
30
35
  </div>
@@ -36,7 +41,12 @@
36
41
  x-ref="action"
37
42
  @click="dismiss"
38
43
  data-role="action">
39
- <%= action %>
44
+ <%= coco_button(
45
+ *@action_data[:args],
46
+ **@action_data[:kwargs],
47
+ size: :sm,
48
+ &@action_data[:block]
49
+ ) %>
40
50
  </div>
41
51
  <% end %>
42
52
 
@@ -45,7 +55,12 @@
45
55
  x-ref="secondaryAction"
46
56
  @click="dismiss"
47
57
  data-role="secondary-action">
48
- <%= secondary_action %>
58
+ <%= coco_button(
59
+ *@secondary_action_data[:args],
60
+ **@secondary_action_data[:kwargs],
61
+ size: :sm,
62
+ &@secondary_action_data[:block]
63
+ ) %>
49
64
  </div>
50
65
  <% end %>
51
66
  </div>
@@ -25,19 +25,19 @@ module Coco
25
25
 
26
26
  renders_one :title
27
27
 
28
- renders_one :action, ->(**kwargs, &block) do
28
+ renders_one :action, ->(*args, **kwargs, &block) do
29
29
  theme = vivid? ? "neutral-dark" : get_option_value(:theme)
30
- Coco::App::Elements::Button.new(**kwargs, theme: theme, size: :sm, icon: nil)
30
+ @action_data = {args: args, kwargs: kwargs.merge(theme: theme), block: block}
31
31
  end
32
32
 
33
- renders_one :secondary_action, ->(**kwargs, &block) do
33
+ renders_one :secondary_action, ->(*args, **kwargs, &block) do
34
34
  theme = vivid? ? "neutral-light" : "text-#{get_option_value(:theme)}"
35
- Coco::App::Elements::Button.new(**kwargs, theme: theme, size: :sm, icon: nil)
35
+ @secondary_action_data = {args: args, kwargs: kwargs.merge(theme: theme), block: block}
36
36
  end
37
37
 
38
- renders_one :link, ->(**kwargs, &block) do
38
+ renders_one :link, ->(*args, **kwargs, &block) do
39
39
  theme = vivid? ? nil : unvividify(get_option_value(:theme))
40
- Coco::App::Elements::Link.new(**kwargs, theme: theme, size: :sm, icon: nil)
40
+ @link_data = {args: args, kwargs: kwargs.merge(theme: theme), block: block}
41
41
  end
42
42
 
43
43
  before_render do
@@ -13,7 +13,7 @@
13
13
 
14
14
  &[data-theme="primary"],
15
15
  &[data-theme="positive"] {
16
- @apply bg-background-primary text-content-light-1 hover:bg-primary-600 active:bg-primary-700;
16
+ @apply bg-background-primary text-content-light-1 hover:bg-primary-600 active:bg-primary-700 antialiased;
17
17
 
18
18
  &[data-state="loading"] {
19
19
  @apply bg-background-primary;
@@ -105,7 +105,7 @@
105
105
  }
106
106
 
107
107
  &[data-theme="negative"] {
108
- @apply bg-background-negative text-content-light-1 hover:bg-negative-700 active:bg-negative-800;
108
+ @apply bg-background-negative text-content-light-1 hover:bg-negative-700 active:bg-negative-800 antialiased;
109
109
 
110
110
  &[data-state="loading"] {
111
111
  @apply bg-background-negative;
@@ -145,7 +145,7 @@
145
145
  }
146
146
 
147
147
  &[data-theme="warning"] {
148
- @apply bg-background-warning text-content-light-1 hover:bg-warning-700 active:bg-warning-800;
148
+ @apply bg-background-warning text-content-light-1 hover:bg-warning-700 active:bg-warning-800 antialiased;
149
149
 
150
150
  &[data-state="loading"] {
151
151
  @apply bg-background-warning;
@@ -185,7 +185,7 @@
185
185
  }
186
186
 
187
187
  &[data-theme="info"] {
188
- @apply bg-background-info text-content-light-1 hover:bg-info-700 active:bg-info-800;
188
+ @apply bg-background-info text-content-light-1 hover:bg-info-700 active:bg-info-800 antialiased;
189
189
 
190
190
  &[data-state="loading"] {
191
191
  @apply bg-background-info;
@@ -225,7 +225,7 @@
225
225
  }
226
226
 
227
227
  &[data-theme="neutral-dark"] {
228
- @apply bg-background-dark-1 text-content-light-1 hover:bg-gray-700 active:bg-gray-600;
228
+ @apply bg-background-dark-1 text-content-light-1 hover:bg-gray-700 active:bg-gray-600 antialiased;
229
229
 
230
230
  &[data-state="loading"] {
231
231
  @apply bg-background-dark-1;
@@ -260,6 +260,30 @@
260
260
  }
261
261
  }
262
262
 
263
+ &[data-theme="text-neutral-light"] {
264
+ @apply bg-transparent text-content-light-1 hover:bg-content-light-1/10 antialiased;
265
+
266
+ &[data-state="active"] {
267
+ @apply bg-content-light-1/10;
268
+ }
269
+
270
+ &[data-disabled="true"] {
271
+ @apply opacity-30;
272
+ }
273
+ }
274
+
275
+ &[data-theme="text-neutral-dark"] {
276
+ @apply bg-transparent text-content-dark-1 hover:bg-content-dark-1/10;
277
+
278
+ &[data-state="active"] {
279
+ @apply bg-content-dark-1/10;
280
+ }
281
+
282
+ &[data-disabled="true"] {
283
+ @apply opacity-30;
284
+ }
285
+ }
286
+
263
287
  /* Responsive resizing */
264
288
 
265
289
  &[data-size="sm"] {
@@ -26,6 +26,8 @@ module Coco
26
26
  "text-toolbar",
27
27
  "neutral-dark",
28
28
  "neutral-light",
29
+ "text-neutral-light",
30
+ "text-neutral-dark",
29
31
  "blank",
30
32
  nil
31
33
  ]
@@ -44,6 +46,21 @@ module Coco
44
46
  end
45
47
  }
46
48
 
49
+ before_initialize do |kwargs|
50
+ kwargs[:button_element] ||= {}
51
+ if kwargs.key?(:modal)
52
+ modal_name = (kwargs[:modal] == true) ? "default" : kwargs[:modal]
53
+ kwargs[:button_element][:data] = kwargs[:button_element].fetch(:data, {}).merge(coco_modal_data_attributes(modal_name))
54
+ kwargs.delete(:modal)
55
+ end
56
+ if kwargs.key?(:frame)
57
+ turbo_data = {turbo: true, turbo_frame: kwargs[:frame]}
58
+ kwargs[:button_element][:data] = kwargs[:button_element].fetch(:data, {}).merge(turbo_data)
59
+ kwargs.delete(:frame)
60
+ end
61
+ kwargs
62
+ end
63
+
47
64
  before_render do
48
65
  if confirm? && !dropdown?
49
66
  with_confirmation do |confirm|
@@ -60,6 +77,10 @@ module Coco
60
77
  def with_confirmation(...)
61
78
  with_dropdown_confirmation(...)
62
79
  end
80
+
81
+ class << self
82
+ include Coco::BaseHelper
83
+ end
63
84
  end
64
85
  end
65
86
  end
@@ -1,10 +1,14 @@
1
1
  @layer components {
2
2
  [data-coco][data-component="app-button-to"] {
3
- @apply inline-flex;
3
+ @apply flex;
4
4
  width: max-content;
5
5
 
6
6
  form {
7
7
  @apply w-full;
8
8
  }
9
+
10
+ &[data-fit="full"] {
11
+ @apply w-full;
12
+ }
9
13
  }
10
14
  }
@@ -3,9 +3,16 @@ module Coco
3
3
  module Elements
4
4
  class ButtonTo < Coco::Component
5
5
  include Concerns::WrapsComponent
6
+ include Concerns::AcceptsOptions
7
+
8
+ accepts_option :fit, from: [:auto, :full]
6
9
 
7
10
  wraps_component :button do |args|
8
- Coco::App::Elements::Button.new(type: :submit, **args)
11
+ Coco::App::Elements::Button.new(
12
+ type: :submit,
13
+ fit: get_option_value(:fit) || :auto,
14
+ **args
15
+ )
9
16
  end
10
17
 
11
18
  %i[confirmation].each do |slot_name|
@@ -9,6 +9,24 @@ module Coco
9
9
 
10
10
  accepts_option :theme, from: THEMES
11
11
  accepts_option :underline, from: [true, false]
12
+
13
+ before_initialize do |kwargs|
14
+ if kwargs.key?(:modal)
15
+ modal_name = (kwargs[:modal] == true) ? "default" : kwargs[:modal]
16
+ kwargs[:data] = kwargs.fetch(:data, {}).merge(coco_modal_data_attributes(modal_name))
17
+ kwargs.delete(:modal)
18
+ end
19
+ if kwargs.key?(:frame)
20
+ turbo_data = {turbo: true, turbo_frame: kwargs[:frame]}
21
+ kwargs[:data] = kwargs.fetch(:data, {}).merge(turbo_data)
22
+ kwargs.delete(:frame)
23
+ end
24
+ kwargs
25
+ end
26
+
27
+ class << self
28
+ include Coco::BaseHelper
29
+ end
12
30
  end
13
31
  end
14
32
  end
@@ -20,6 +20,10 @@
20
20
  @apply !font-[400];
21
21
  }
22
22
  }
23
+
24
+ .divider {
25
+ @apply my-1.5;
26
+ }
23
27
  }
24
28
 
25
29
  &[data-size="sm"] {
@@ -1,5 +1,11 @@
1
1
  <%= render component_tag(x: {data: "appMenuButton"}) do %>
2
2
  <%= render button do |btn| %>
3
+ <% if icon? %>
4
+ <% btn.with_icon do %>
5
+ <%= icon %>
6
+ <% end %>
7
+ <% end %>
8
+
3
9
  <% if menu? %>
4
10
  <% btn.with_dropdown do %>
5
11
  <%= menu %>
@@ -3,11 +3,17 @@ module Coco
3
3
  module Elements
4
4
  class MenuButton < Coco::Component
5
5
  include Concerns::AcceptsOptions
6
+ include Concerns::WithIcon
6
7
  include Concerns::WrapsComponent
7
8
  include Coco::AppHelper
8
9
 
9
- wraps_component :button do |args|
10
- Coco::App::Elements::Button.new(toggle: :vertical, fit: get_option_value(:fit) || :auto, **args)
10
+ wraps_component :button do |kwargs|
11
+ @size = kwargs.fetch(:size, :default)&.to_sym
12
+ if @size.in?(Coco::App::Elements::Button::SIZE_ALIASES.keys) && !kwargs.key?(:resize)
13
+ @size, @resize = Coco::App::Elements::Button::SIZE_ALIASES.fetch(@size)
14
+ end
15
+
16
+ Coco::App::Elements::Button.new(toggle: :vertical, fit: get_option_value(:fit) || :auto, **kwargs)
11
17
  end
12
18
 
13
19
  accepts_option :fit, from: [:auto, :full]
@@ -20,13 +26,6 @@ module Coco
20
26
 
21
27
  attr_reader :size, :resize
22
28
 
23
- def initialize(button: {}, **kwargs)
24
- @size = kwargs.fetch(:size, :default)&.to_sym
25
- if @size.in?(Coco::App::Elements::Button::SIZE_ALIASES.keys) && !kwargs.key?(:resize)
26
- @size, @resize = Coco::App::Elements::Button::SIZE_ALIASES.fetch(@size)
27
- end
28
- end
29
-
30
29
  def button_text
31
30
  text || content
32
31
  end
@@ -12,8 +12,8 @@ module Coco
12
12
  end
13
13
 
14
14
  %i[title action secondary_action link].each do |slot_name|
15
- renders_one slot_name, ->(**kwargs, &block) do
16
- alert.send("with_#{slot_name}".to_sym, **kwargs, &block)
15
+ renders_one slot_name, ->(*args, **kwargs, &block) do
16
+ alert.send("with_#{slot_name}".to_sym, *args, **kwargs, &block)
17
17
  end
18
18
  end
19
19
  end
@@ -35,7 +35,7 @@
35
35
  /* disabled */
36
36
 
37
37
  &[data-disabled="true"] .button-element {
38
- @apply cursor-not-allowed;
38
+ @apply cursor-not-allowed pointer-events-none;
39
39
  }
40
40
 
41
41
  /* loading */
@@ -35,11 +35,15 @@
35
35
  }
36
36
 
37
37
  &[data-size="xl"] {
38
- @apply w-9 h-9;
38
+ @apply w-8 h-8;
39
39
  }
40
40
 
41
41
  &[data-size="xxl"] {
42
- @apply w-12 h-12;
42
+ @apply w-10 h-10;
43
+ }
44
+
45
+ &[data-size="full"] {
46
+ @apply w-full h-full;
43
47
  }
44
48
 
45
49
  /* Motion */
@@ -6,7 +6,7 @@ module Coco
6
6
 
7
7
  InvalidIconError = Class.new(StandardError)
8
8
 
9
- accepts_option :size, from: %i[xs sm md lg xl xxl]
9
+ accepts_option :size, from: %i[xs sm md lg xl xxl full]
10
10
  accepts_option :spin, from: [true, false]
11
11
  accepts_option :style, from: [:line, :fill, :custom]
12
12
 
@@ -7,7 +7,8 @@
7
7
  }
8
8
 
9
9
  .modal-container {
10
- @apply relative flex min-h-screen justify-center items-center z-[10000] p-2 sm:p-8;
10
+ @apply relative flex justify-center items-center z-[10000] p-2 sm:p-8;
11
+ min-height: var(--app-height);
11
12
  }
12
13
 
13
14
  .modal-content {
@@ -1,4 +1,5 @@
1
1
  import { CocoComponent } from "@js/coco";
2
+ import { hideAll } from "@libs/tippy";
2
3
 
3
4
  export default CocoComponent("modal", () => {
4
5
  return {
@@ -19,6 +20,7 @@ export default CocoComponent("modal", () => {
19
20
 
20
21
  show() {
21
22
  this.open = true;
23
+ hideAll();
22
24
  setTimeout(() => {
23
25
  this.$dispatch("modal:shown");
24
26
  }, 400);
@@ -16,12 +16,12 @@ export default CocoComponent("modalLightbox", () => {
16
16
 
17
17
  imageLoaded() {
18
18
  this.loaded = true;
19
- this.$nextTick(() => {
19
+ setTimeout(() => {
20
20
  const scrollTop = parseInt(this.img.dataset.scrollTop, 10);
21
21
  if (!isNaN(scrollTop) && scrollTop !== 0) {
22
22
  this.modal.scrollTo(scrollTop);
23
23
  }
24
- });
24
+ }, 200);
25
25
  },
26
26
 
27
27
  get img() {
@@ -1,6 +1,20 @@
1
1
  @layer components {
2
2
  [data-coco][data-component="placeholder"] {
3
- @apply border border-dashed border-gray-400 p-4 bg-gray-50 text-center;
3
+ @apply p-4;
4
+
5
+ &[data-boxed="true"] {
6
+ @apply border border-dashed border-gray-400 bg-gray-50;
7
+ }
8
+
9
+ &[data-prose="true"] {
10
+ .placeholder-content {
11
+ @apply space-y-3;
12
+ }
13
+ }
14
+
15
+ &[data-prose="false"] {
16
+ @apply text-center;
17
+ }
4
18
 
5
19
  &[data-size="full"] {
6
20
  @apply w-full h-full;
@@ -3,5 +3,7 @@ module Coco
3
3
  include Concerns::AcceptsOptions
4
4
 
5
5
  accepts_option :size, from: [:auto, :full], default: :auto
6
+ accepts_option :prose, from: [true, false], default: false
7
+ accepts_option :boxed, from: [true, false], default: true
6
8
  end
7
9
  end
@@ -4,24 +4,37 @@ module Coco
4
4
  extend ActiveSupport::Concern
5
5
  include Coco::AppHelper
6
6
 
7
+ BUTTON_TYPES = {
8
+ menu: "Coco::App::Elements::MenuButton",
9
+ color_picker: "Coco::App::Elements::ColorPickerButton",
10
+ layout_picker: "Coco::App::Elements::LayoutPickerButton",
11
+ image_picker: "Coco::App::Elements::ImagePickerButton",
12
+ dropdown: "Coco::App::Elements::DropdownButton"
13
+ }
14
+
7
15
  included do
8
16
  renders_many :items, types: {
9
17
  divider: ->(**kwargs) { tag.div(class: "divider") },
10
- button: ->(**kwargs) {
11
- if kwargs.key?(:action) || kwargs.key?(:method) || kwargs.key?(:params)
12
- App::Elements::ButtonTo.new(**button_kwargs(kwargs, :button_to))
13
- else
14
- App::Elements::Button.new(**button_kwargs(kwargs, :button))
15
- end
16
- },
17
- menu_button: ->(**kwargs) { App::Elements::MenuButton.new(**button_kwargs(kwargs, :menu)) },
18
- color_picker_button: ->(**kwargs) { App::Elements::ColorPickerButton.new(**button_kwargs(kwargs, :color_picker)) },
19
- layout_picker_button: ->(**kwargs) { App::Elements::LayoutPickerButton.new(**button_kwargs(kwargs, :layout_picker)) },
20
- image_picker_button: ->(**kwargs) { App::Elements::ImagePickerButton.new(**button_kwargs(kwargs, :image_picker)) },
21
- dropdown_button: ->(**kwargs) { App::Elements::DropdownButton.new(**button_kwargs(kwargs, :dropdown)) }
18
+ button: ->(*args, **kwargs, &block) { coco_button(*args, **button_kwargs(kwargs, :button), &block) },
19
+ menu_button: ->(*args, **kwargs, &block) { instantiate_button(:menu, *args, **kwargs, &block) },
20
+ dropdown_button: ->(*args, **kwargs, &block) { instantiate_button(:dropdown, *args, **kwargs, &block) },
21
+ color_picker_button: ->(*args, **kwargs, &block) { instantiate_button(:color_picker, *args, **kwargs, &block) },
22
+ image_picker_button: ->(*args, **kwargs, &block) { instantiate_button(:image_picker, *args, **kwargs, &block) },
23
+ layout_picker_button: ->(*args, **kwargs, &block) { instantiate_button(:layout_picker, *args, **kwargs, &block) }
22
24
  }
23
25
  end
24
26
 
27
+ def instantiate_button(type, *args, **kwargs, &block)
28
+ href, content = if block
29
+ [args.first, nil]
30
+ else
31
+ (args.size == 1) ? [nil, args.first] : args[0..2].reverse!
32
+ end
33
+ component = BUTTON_TYPES[type].constantize.new(href: href, **button_kwargs(kwargs, type))
34
+ component.with_content(content) if !block && content.present?
35
+ component
36
+ end
37
+
25
38
  def with_divider(...)
26
39
  with_item_divider(...)
27
40
  end
@@ -1,28 +1,24 @@
1
1
  module Coco
2
2
  module AppHelper
3
- def coco_link(*args, **kwargs, &block)
4
- href, content = args[0..2].reverse!
5
-
6
- if kwargs.key?(:modal)
7
- modal_name = (kwargs[:modal] == true) ? "default" : kwargs[:modal]
8
- kwargs[:data] = kwargs.fetch(:data, {}).merge(coco_modal_data_attributes(modal_name))
9
- kwargs.delete(:modal)
10
- end
11
-
12
- if kwargs.key?(:frame)
13
- turbo_data = {turbo: true, turbo_frame: kwargs[:frame]}
14
- kwargs[:data] = kwargs.fetch(:data, {}).merge(turbo_data)
15
- kwargs.delete(:frame)
3
+ def coco_link(*args, **, &block)
4
+ href, content = if block
5
+ [args.first, nil]
6
+ else
7
+ (args.size == 1) ? [nil, args.first] : args[0..2].reverse!
16
8
  end
17
9
 
18
- link = Coco::App::Elements::Link.new(href: href, **kwargs)
10
+ link = Coco::App::Elements::Link.new(href: href, **)
19
11
  link = link.with_content(content) if !block && content.present?
20
12
 
21
13
  render(link, &block)
22
14
  end
23
15
 
24
16
  def coco_button(*args, **kwargs, &block)
25
- href, content = args[0..2].reverse!
17
+ href, content = if block
18
+ [args.first, nil]
19
+ else
20
+ (args.size == 1) ? [nil, args.first] : args[0..2].reverse!
21
+ end
26
22
 
27
23
  button = if kwargs.key?(:action) || kwargs.key?(:method) || kwargs.key?(:params)
28
24
  "ButtonTo"
@@ -30,20 +26,6 @@ module Coco
30
26
  "Button"
31
27
  end
32
28
 
33
- kwargs[:button_element] ||= {}
34
-
35
- if kwargs.key?(:modal)
36
- modal_name = (kwargs[:modal] == true) ? "default" : kwargs[:modal]
37
- kwargs[:button_element][:data] = kwargs[:button_element].fetch(:data, {}).merge(coco_modal_data_attributes(modal_name))
38
- kwargs.delete(:modal)
39
- end
40
-
41
- if kwargs.key?(:frame)
42
- turbo_data = {turbo: true, turbo_frame: kwargs[:frame]}
43
- kwargs[:button_element][:data] = kwargs[:button_element].fetch(:data, {}).merge(turbo_data)
44
- kwargs.delete(:frame)
45
- end
46
-
47
29
  component = "Coco::App::Elements::#{button}".constantize.new(href: href, **kwargs)
48
30
  component = component.with_content(content) if !block && content.present?
49
31
 
@@ -56,6 +56,8 @@ module Coco
56
56
  end
57
57
 
58
58
  def coco_modal_data_attributes(name = "default")
59
+ return {} if name.nil?
60
+
59
61
  {
60
62
  turbo: true,
61
63
  turbo_frame: coco_modal_frame_id(name)
@@ -9,7 +9,11 @@ module Coco
9
9
 
10
10
  href = Coco::ActionViewHelper.url_target(name, options)
11
11
 
12
- coco_link(name, href, **html_options.symbolize_keys!, &block)
12
+ if block
13
+ coco_link(href, **html_options.symbolize_keys!, &block)
14
+ else
15
+ coco_link(name, href, **html_options.symbolize_keys!)
16
+ end
13
17
  end
14
18
 
15
19
  def coco_button_to(name = nil, options = nil, html_options = nil, &block)
@@ -26,6 +26,9 @@ module.exports = {
26
26
  spin: "spin 1.5s linear infinite",
27
27
  "spin-reverse": "spin 1.5s linear infinite reverse",
28
28
  },
29
+ width: {
30
+ 18: "4.5rem",
31
+ },
29
32
  customForms: () => ({
30
33
  DEFAULT: {
31
34
  checkbox: {
data/config/tokens.cjs CHANGED
@@ -136,6 +136,7 @@ const colorAliases = {
136
136
  DEFAULT: colors.green[500],
137
137
  dark: colors.green[600],
138
138
  inverse: colors.green[300],
139
+ "inverse-vivid": "#009979",
139
140
  },
140
141
  negative: {
141
142
  DEFAULT: colors.red[600],
@@ -168,6 +169,7 @@ const screens = {
168
169
  xl: "1200px",
169
170
  "2xl": "1400px",
170
171
  max: "1800px",
172
+ "small-landscape": { raw: "(max-height: 760px) and (min-width: 576px)" },
171
173
  print: { raw: "print" }, // Note: PDFs are rendered at a viewport width of 1280px
172
174
  };
173
175
 
@@ -177,6 +179,7 @@ const fontSize = {
177
179
  "para-md": ["16px", "24px"],
178
180
  "para-lg": ["18px", "27px"],
179
181
 
182
+ "label-xxs": ["10px", "12px"],
180
183
  "label-xs": ["12px", "14px"],
181
184
  "label-sm": ["14px", "16px"],
182
185
  "label-md": ["16px", "20px"],
data/lib/coco.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Coco
2
- VERSION = "0.7.8"
2
+ VERSION = "0.7.10"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: coveragebook_components
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.8
4
+ version: 0.7.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mark Perkins
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-10-13 00:00:00.000000000 Z
11
+ date: 2023-10-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -1323,6 +1323,7 @@ files:
1323
1323
  - app/assets/img/test/slides/slide-foreground-portrait.jpg
1324
1324
  - app/assets/js/app.js
1325
1325
  - app/assets/js/app/components.js
1326
+ - app/assets/js/app/setup.js
1326
1327
  - app/assets/js/base/components.js
1327
1328
  - app/assets/js/book.js
1328
1329
  - app/assets/js/book/components.js
@@ -1332,6 +1333,7 @@ files:
1332
1333
  - app/assets/js/helpers/dom.js
1333
1334
  - app/assets/js/helpers/file.js
1334
1335
  - app/assets/js/helpers/lang.js
1336
+ - app/assets/js/helpers/location.js
1335
1337
  - app/assets/js/helpers/path.js
1336
1338
  - app/assets/js/helpers/screenshot.js
1337
1339
  - app/assets/js/helpers/turbo_events.js