coveragebook_components 0.17.7 → 0.18.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5535752274648feee015c6471880b40d3ddc2cd63e8836ec3839b7461917e530
4
- data.tar.gz: 34fba281df9eddd0a2f1449bb8b4abcbb1cae0e4fdcee50c9d7db71c814abf8b
3
+ metadata.gz: a6e884ae365d700946ff6b8fcaba45157c23dd63f1c99eb9bfe479d8ffee61c1
4
+ data.tar.gz: 74c0748337f4a09bea38d496e71c7c62f39282fdb457bb8bc443507171f58ba2
5
5
  SHA512:
6
- metadata.gz: c8b43623f1feeffe47afe6b28fd418b0e3be58ff0059eeb20eb522f33617a781a9e140645aaeee5096b678e99aa5abb346e02904b8a12e974c1a7b991f066464
7
- data.tar.gz: 1da47f77ae7ce00536379c4e05368b3c24ef7e1331f2e9f7fbc15f56c63f157b2e337c37ba44df3af140599f22f1e1a1ad1ae189f5ffdced64b9b83cadd4a3d4
6
+ metadata.gz: 7213a41ac90c6eb3288873ca5f82f36a6dd816cb98e865fe9089a7962c8efc5b8052926ac67d709b4c87a2c06af34cb2b8a61af8a07bb2fd2abcbfd70994fb11
7
+ data.tar.gz: 248c6c5d9c9d17a8aef5de3c352cb0148c0574dd516272344fdbb01633afe3673279f1357a66c10d1c74ce46640cfbcaf6297dbddcdcafd206ce0911457535eb
@@ -4161,6 +4161,11 @@ select{
4161
4161
  padding-bottom: 1rem
4162
4162
  }
4163
4163
 
4164
+ [data-coco][data-component="popover"] {
4165
+ display: none;
4166
+ pointer-events: none;
4167
+ }
4168
+
4164
4169
  [data-coco][data-component="snackbar"]{
4165
4170
  width: 100%;
4166
4171
  overflow: hidden;
@@ -5779,10 +5784,6 @@ select{
5779
5784
  position: fixed
5780
5785
  }
5781
5786
 
5782
- .\!block{
5783
- display: block !important
5784
- }
5785
-
5786
5787
  .block{
5787
5788
  display: block
5788
5789
  }
@@ -6963,3 +6964,56 @@ select{
6963
6964
  width: -moz-min-content;
6964
6965
  width: min-content;
6965
6966
  }
6967
+
6968
+ /* Tippy popover theme */
6969
+
6970
+ .tippy-box[data-theme^="coco-popover-"]{
6971
+ border-radius: 0.5rem;
6972
+ border-style: none;
6973
+ padding: 1.5rem;
6974
+ font-size: 16px;
6975
+ line-height: 24px;
6976
+ font-weight: 400;
6977
+ --tw-text-opacity: 1;
6978
+ color: rgb(255 255 255 / var(--tw-text-opacity));
6979
+ --tw-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
6980
+ --tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);
6981
+ box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
6982
+ width: -moz-fit-content;
6983
+ width: fit-content
6984
+ }
6985
+
6986
+ .tippy-box[data-theme^="coco-popover-"] .tippy-svg-arrow > svg:first-child{
6987
+ display: none
6988
+ }
6989
+
6990
+ .tippy-box[data-theme~="coco-popover-neutral"]{
6991
+ border-width: 1px;
6992
+ border-style: solid;
6993
+ --tw-bg-opacity: 1;
6994
+ background-color: rgb(255 255 255 / var(--tw-bg-opacity));
6995
+ --tw-text-opacity: 1;
6996
+ color: rgb(17 24 39 / var(--tw-text-opacity));
6997
+ background-blend-mode: hard-light;
6998
+ border-color: rgba(0, 12, 39, 0.1)
6999
+ }
7000
+
7001
+ .tippy-box[data-theme~="coco-popover-neutral"] .tippy-svg-arrow > svg:first-child{
7002
+ display: block;
7003
+ fill: #D1D5DB
7004
+ }
7005
+
7006
+ .tippy-box[data-theme~="coco-popover-neutral"] .tippy-svg-arrow > svg:last-child{
7007
+ fill: #FFFFFF
7008
+ }
7009
+
7010
+ .tippy-box[data-theme~="coco-popover-info"]{
7011
+ --tw-bg-opacity: 1;
7012
+ background-color: rgb(2 132 199 / var(--tw-bg-opacity));
7013
+ -webkit-font-smoothing: antialiased;
7014
+ -moz-osx-font-smoothing: grayscale
7015
+ }
7016
+
7017
+ .tippy-box[data-theme~="coco-popover-info"] .tippy-svg-arrow > svg:last-child{
7018
+ fill: #0284C7
7019
+ }
@@ -15260,7 +15260,7 @@ function dropdown_default(Alpine3) {
15260
15260
  const settings = tippyModifiers(modifiers);
15261
15261
  const result = expression ? evaluate(expression) : {};
15262
15262
  const directiveConfig = isObject(result) ? result : {};
15263
- let { triggerTarget, contentTarget, anchorTarget, ...config } = directiveConfig;
15263
+ let { triggerTarget, contentTarget, anchorTarget, flip, ...config } = directiveConfig;
15264
15264
  contentTarget = contentTarget || el.querySelector("[x-dropdown\\:content]");
15265
15265
  const content = isNode(contentTarget) ? contentTarget.firstElementChild : contentTarget;
15266
15266
  triggerTarget = triggerTarget || el.querySelector("[x-dropdown\\:trigger]") || el;
@@ -15288,6 +15288,9 @@ function dropdown_default(Alpine3) {
15288
15288
  interactive: true,
15289
15289
  animation: false,
15290
15290
  maxWidth: 380,
15291
+ popperOptions: {
15292
+ modifiers: [{ name: "flip", enabled: flip !== false }]
15293
+ },
15291
15294
  triggerTarget,
15292
15295
  content,
15293
15296
  onShow: (...args) => {
@@ -15441,7 +15444,7 @@ var alpine_default = import_alpinejs.default;
15441
15444
  // ../../../package.json
15442
15445
  var package_default = {
15443
15446
  name: "coveragebook-components",
15444
- version: "0.17.7",
15447
+ version: "0.18.1",
15445
15448
  repository: "git@github.com:coveragebook/coco.git",
15446
15449
  license: "NO LICENSE",
15447
15450
  author: "Mark Perkins <mark@coveragebook.com>",
@@ -16195,6 +16198,112 @@ var notice_default = CocoComponent("notice", () => {
16195
16198
  return {};
16196
16199
  });
16197
16200
 
16201
+ // ../../components/coco/messaging/popover/popover.js
16202
+ var popover_exports = {};
16203
+ __export(popover_exports, {
16204
+ default: () => popover_default
16205
+ });
16206
+ var popover_default = CocoComponent("popover", ({ target, trigger, options = {} }) => {
16207
+ return {
16208
+ targetEl: null,
16209
+ open: false,
16210
+ init() {
16211
+ this.targetEl = target ? document.querySelector(target) : this.$el.parentElement;
16212
+ if (this.targetEl) {
16213
+ this.targetEl.coco_popover = this;
16214
+ if (trigger == "click") {
16215
+ this.targetEl.style.cursor = "pointer";
16216
+ }
16217
+ this.$nextTick(() => {
16218
+ const content = this.$el.firstElementChild;
16219
+ content.__popover_target = this.targetEl;
16220
+ tippy_default(this.targetEl, {
16221
+ trigger,
16222
+ theme: this.theme,
16223
+ maxWidth: "none",
16224
+ interactive: true,
16225
+ allowHTML: true,
16226
+ appendTo: () => document.body,
16227
+ content: () => content,
16228
+ onShown: () => {
16229
+ this.open = true;
16230
+ },
16231
+ onHidden: () => {
16232
+ this.open = false;
16233
+ },
16234
+ ...options
16235
+ });
16236
+ });
16237
+ } else {
16238
+ console.error(`Popover target '${target} not found.'`);
16239
+ }
16240
+ },
16241
+ show(event) {
16242
+ if (!event || this.eventTarget(event) === this.targetEl && this.popoverInstance) {
16243
+ this.popoverInstance.show();
16244
+ }
16245
+ },
16246
+ hide(event) {
16247
+ if (!event || this.eventTarget(event) === this.targetEl && this.popoverInstance) {
16248
+ this.popoverInstance.hide();
16249
+ }
16250
+ },
16251
+ toggle(event) {
16252
+ if (!event || this.eventTarget(event) === this.targetEl && this.popoverInstance) {
16253
+ this.open ? this.popoverInstance.hide() : this.popoverInstance.show();
16254
+ }
16255
+ },
16256
+ destroy() {
16257
+ if (this.popoverInstance) {
16258
+ this.popoverInstance.destroy();
16259
+ }
16260
+ },
16261
+ eventTarget(event) {
16262
+ if (event.detail.target) {
16263
+ if (typeof event.detail.target === "string") {
16264
+ return document.querySelector(event.detail.target);
16265
+ } else {
16266
+ return event.detail.target;
16267
+ }
16268
+ } else {
16269
+ return event.target;
16270
+ }
16271
+ },
16272
+ get theme() {
16273
+ return `coco-popover-${this.$root.getAttribute("data-theme")}`;
16274
+ },
16275
+ get popoverInstance() {
16276
+ if (this.targetEl) {
16277
+ return this.targetEl._tippy;
16278
+ }
16279
+ }
16280
+ };
16281
+ });
16282
+
16283
+ // ../../components/coco/messaging/popover/popover_content.js
16284
+ var popover_content_exports = {};
16285
+ __export(popover_content_exports, {
16286
+ default: () => popover_content_default
16287
+ });
16288
+ var popover_content_default = CocoComponent("popoverContent", () => {
16289
+ return {
16290
+ init() {
16291
+ this.hide = this.hide.bind(this);
16292
+ this.show = this.show.bind(this);
16293
+ this.toggle = this.toggle.bind(this);
16294
+ },
16295
+ hide() {
16296
+ this.$dispatch("popover:hide", { target: this.$root.__popover_target });
16297
+ },
16298
+ show() {
16299
+ this.$dispatch("popover:show", { target: this.$root.__popover_target });
16300
+ },
16301
+ toggle() {
16302
+ this.$dispatch("popover:toggle", { target: this.$root.__popover_target });
16303
+ }
16304
+ };
16305
+ });
16306
+
16198
16307
  // ../../components/coco/messaging/snackbar/snackbar.js
16199
16308
  var snackbar_exports = {};
16200
16309
  __export(snackbar_exports, {
@@ -16401,7 +16510,7 @@ var tooltip_default2 = CocoComponent("tooltip", () => {
16401
16510
  });
16402
16511
 
16403
16512
  // import-glob:/Users/mark/Code/coveragebook/coco/app/assets/js/base|@components/messaging/**/*.js
16404
- var modules7 = [alert_exports, notice_exports, snackbar_exports, system_banner_exports, toast_exports, tooltip_exports];
16513
+ var modules7 = [alert_exports, notice_exports, popover_exports, popover_content_exports, snackbar_exports, system_banner_exports, toast_exports, tooltip_exports];
16405
16514
  var __default7 = modules7;
16406
16515
 
16407
16516
  // ../../components/coco/modals/modal/modal.js
@@ -16,7 +16,7 @@ export default function (Alpine) {
16
16
  const settings = buildConfig(modifiers);
17
17
  const result = expression ? evaluate(expression) : {};
18
18
  const directiveConfig = isObject(result) ? result : {};
19
- let { triggerTarget, contentTarget, anchorTarget, ...config } =
19
+ let { triggerTarget, contentTarget, anchorTarget, flip, ...config } =
20
20
  directiveConfig;
21
21
 
22
22
  contentTarget =
@@ -61,6 +61,9 @@ export default function (Alpine) {
61
61
  interactive: true,
62
62
  animation: false,
63
63
  maxWidth: 380,
64
+ popperOptions: {
65
+ modifiers: [{ name: "flip", enabled: flip !== false }],
66
+ },
64
67
 
65
68
  triggerTarget,
66
69
  content,
@@ -55,6 +55,7 @@ module Coco
55
55
  dd.accepts_option :placement,
56
56
  from: %w[top top-start top-end right right-start right-end bottom bottom-start bottom-end left left-start left-end auto auto-start auto-end],
57
57
  private: true
58
+ dd.accepts_option :flip, from: [true, false], default: true, private: true
58
59
  end
59
60
 
60
61
  renders_one :text, Coco::Content
@@ -154,7 +155,7 @@ module Coco
154
155
  if dropdown? || confirm?
155
156
  {
156
157
  data: x_data("buttonDropdown"),
157
- dropdown: jsify_data({placement: get_option_value(:dropdown, :placement)}.compact),
158
+ dropdown: jsify_data({placement: get_option_value(:dropdown, :placement), flip: get_option_value(:dropdown, :flip)}.compact),
158
159
  bind: "root"
159
160
  }
160
161
  end
@@ -16,21 +16,17 @@ module Coco
16
16
  divider: ->(**kwargs) { tag.div(class: "divider") },
17
17
  html: ->(&block) { block.call },
18
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
- color_picker_button: ->(*args, **kwargs, &block) { instantiate_button(:color_picker, *args, **kwargs, &block) },
21
- image_picker_button: ->(*args, **kwargs, &block) { instantiate_button(:image_picker, *args, **kwargs, &block) },
22
- layout_picker_button: ->(*args, **kwargs, &block) { instantiate_button(:layout_picker, *args, **kwargs, &block) }
19
+ menu_button: ->(*args, **kwargs, &block) { instantiate_button(:menu, args.first, nil, **kwargs, &block) },
20
+ color_picker_button: ->(*args, **kwargs, &block) { instantiate_button(:color_picker, args.first, nil, **kwargs, &block) },
21
+ image_picker_button: ->(*args, **kwargs, &block) { instantiate_button(:image_picker, args.first, nil, **kwargs, &block) },
22
+ layout_picker_button: ->(*args, **kwargs, &block) { instantiate_button(:layout_picker, args.first, nil, **kwargs, &block) }
23
23
  }
24
24
  end
25
25
 
26
26
  def instantiate_button(type, *args, **kwargs, &block)
27
- href, content = if block
28
- [args.first, nil]
29
- else
30
- (args.size == 1) ? [nil, args.first] : args[0..2].reverse!
31
- end
32
- component = BUTTON_TYPES[type].constantize.new(href: href, **button_kwargs(kwargs, type))
33
- component.with_content(content) if !block && content.present?
27
+ href, content = (args.size == 1) ? [nil, args.first] : args[0..2].reverse!
28
+ component = BUTTON_TYPES[type].constantize.new(text: content, href: href, **button_kwargs(kwargs, type))
29
+ component.with_text(content) if content.present?
34
30
  component
35
31
  end
36
32
 
@@ -0,0 +1,37 @@
1
+ @layer components {
2
+ [data-coco][data-component="popover"] {
3
+ display: none;
4
+ pointer-events: none;
5
+ }
6
+ }
7
+
8
+ /* Tippy popover theme */
9
+ .tippy-box[data-theme^="coco-popover-"] {
10
+ @apply text-content-light-1 text-para-md border-none shadow-xl rounded-lg p-6 font-normal;
11
+ width: fit-content;
12
+
13
+ .tippy-svg-arrow > svg:first-child {
14
+ @apply hidden;
15
+ }
16
+ }
17
+
18
+ .tippy-box[data-theme~="coco-popover-neutral"] {
19
+ @apply bg-background-light-1 text-content-dark-1 border border-solid border-gray-blend-100;
20
+
21
+ .tippy-svg-arrow > svg:first-child {
22
+ @apply block;
23
+ @apply fill-coco-gray-300;
24
+ }
25
+
26
+ .tippy-svg-arrow > svg:last-child {
27
+ @apply fill-background-light-1;
28
+ }
29
+ }
30
+
31
+ .tippy-box[data-theme~="coco-popover-info"] {
32
+ @apply bg-background-info antialiased;
33
+
34
+ .tippy-svg-arrow > svg:last-child {
35
+ @apply fill-background-info;
36
+ }
37
+ }
@@ -0,0 +1,10 @@
1
+ <%= render component_tag(x: {
2
+ data: "popover({target: #{target.to_json}, trigger: #{trigger.to_json}, options: #{options.to_json}})",
3
+ "@popover:show.document": "show",
4
+ "@popover:hide.document": "hide",
5
+ "@popover:toggle.document": "toggle"
6
+ }) do %>
7
+ <div x-data="popoverContent">
8
+ <%= content %>
9
+ </div>
10
+ <% end %>
@@ -0,0 +1,103 @@
1
+ import { CocoComponent } from "@assets/js/coco/component";
2
+ import tippy from "@js/base/tippy";
3
+ import { getData } from "@helpers/alpine";
4
+
5
+ export default CocoComponent("popover", ({ target, trigger, options = {} }) => {
6
+ return {
7
+ targetEl: null,
8
+ open: false,
9
+
10
+ init() {
11
+ this.targetEl = target
12
+ ? document.querySelector(target)
13
+ : this.$el.parentElement;
14
+
15
+ if (this.targetEl) {
16
+ this.targetEl.coco_popover = this;
17
+
18
+ if (trigger == "click") {
19
+ this.targetEl.style.cursor = "pointer";
20
+ }
21
+
22
+ this.$nextTick(() => {
23
+ const content = this.$el.firstElementChild;
24
+ content.__popover_target = this.targetEl;
25
+
26
+ tippy(this.targetEl, {
27
+ trigger,
28
+ theme: this.theme,
29
+ maxWidth: "none",
30
+ interactive: true,
31
+ allowHTML: true,
32
+ appendTo: () => document.body,
33
+ content: () => content,
34
+ onShown: () => {
35
+ this.open = true;
36
+ },
37
+ onHidden: () => {
38
+ this.open = false;
39
+ },
40
+ ...options,
41
+ });
42
+ });
43
+ } else {
44
+ console.error(`Popover target '${target} not found.'`);
45
+ }
46
+ },
47
+
48
+ show(event) {
49
+ if (
50
+ !event ||
51
+ (this.eventTarget(event) === this.targetEl && this.popoverInstance)
52
+ ) {
53
+ this.popoverInstance.show();
54
+ }
55
+ },
56
+
57
+ hide(event) {
58
+ if (
59
+ !event ||
60
+ (this.eventTarget(event) === this.targetEl && this.popoverInstance)
61
+ ) {
62
+ this.popoverInstance.hide();
63
+ }
64
+ },
65
+
66
+ toggle(event) {
67
+ if (
68
+ !event ||
69
+ (this.eventTarget(event) === this.targetEl && this.popoverInstance)
70
+ ) {
71
+ this.open ? this.popoverInstance.hide() : this.popoverInstance.show();
72
+ }
73
+ },
74
+
75
+ destroy() {
76
+ if (this.popoverInstance) {
77
+ this.popoverInstance.destroy();
78
+ }
79
+ },
80
+
81
+ eventTarget(event) {
82
+ if (event.detail.target) {
83
+ if (typeof event.detail.target === "string") {
84
+ return document.querySelector(event.detail.target);
85
+ } else {
86
+ return event.detail.target;
87
+ }
88
+ } else {
89
+ return event.target;
90
+ }
91
+ },
92
+
93
+ get theme() {
94
+ return `coco-popover-${this.$root.getAttribute("data-theme")}`;
95
+ },
96
+
97
+ get popoverInstance() {
98
+ if (this.targetEl) {
99
+ return this.targetEl._tippy;
100
+ }
101
+ },
102
+ };
103
+ });
@@ -0,0 +1,37 @@
1
+ module Coco
2
+ class Popover < Coco::Component
3
+ include Concerns::AcceptsOptions
4
+
5
+ accepts_option :theme, from: ["netural", "info"], default: "neutral"
6
+ accepts_option :trigger, from: ["click", "manual", "hover"], default: "click"
7
+ accepts_option :placement,
8
+ from: %w[top top-start top-end right right-start right-end bottom bottom-start bottom-end left left-start left-end auto auto-start auto-end],
9
+ default: "auto",
10
+ private: true
11
+
12
+ before_initialize do |kwargs|
13
+ [:placement, :trigger, :theme].each do |key|
14
+ kwargs[key] = kwargs[key].to_s.tr("_", "-") if kwargs.key?(key)
15
+ end
16
+ kwargs
17
+ end
18
+
19
+ attr_reader :target
20
+
21
+ def initialize(target: nil, options: {}, **)
22
+ @target = target
23
+ @options = options
24
+ end
25
+
26
+ def trigger
27
+ (get_option_value(:trigger) == "hover") ? "mouseenter focus" : get_option_value(:trigger)
28
+ end
29
+
30
+ def options
31
+ {
32
+ placement: get_option_value(:placement),
33
+ **@options
34
+ }
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,24 @@
1
+ import { CocoComponent } from "@assets/js/coco/component";
2
+ import { getData } from "@helpers/alpine";
3
+
4
+ export default CocoComponent("popoverContent", () => {
5
+ return {
6
+ init() {
7
+ this.hide = this.hide.bind(this);
8
+ this.show = this.show.bind(this);
9
+ this.toggle = this.toggle.bind(this);
10
+ },
11
+
12
+ hide() {
13
+ this.$dispatch("popover:hide", { target: this.$root.__popover_target });
14
+ },
15
+
16
+ show() {
17
+ this.$dispatch("popover:show", { target: this.$root.__popover_target });
18
+ },
19
+
20
+ toggle() {
21
+ this.$dispatch("popover:toggle", { target: this.$root.__popover_target });
22
+ },
23
+ };
24
+ });
@@ -27,8 +27,8 @@ module Coco
27
27
  render(Coco::ButtonGroup.new(**), &)
28
28
  end
29
29
 
30
- def coco_menu_button(**, &)
31
- render(Coco::MenuButton.new(**), &)
30
+ def coco_menu_button(text = nil, **, &)
31
+ render(Coco::MenuButton.new(text: text, **), &)
32
32
  end
33
33
 
34
34
  def coco_menu_item(type, **, &)
@@ -166,6 +166,10 @@ module Coco
166
166
  render(Coco::SystemBanner.new(**), &)
167
167
  end
168
168
 
169
+ def coco_popover(**, &)
170
+ render(Coco::Popover.new(**), &)
171
+ end
172
+
169
173
  # Modals
170
174
 
171
175
  def coco_modal(name = "default", **, &)
data/lib/coco.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Coco
2
- VERSION = "0.17.7"
2
+ VERSION = "0.18.1"
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.17.7
4
+ version: 0.18.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mark Perkins
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-04-18 00:00:00.000000000 Z
11
+ date: 2024-05-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -1647,6 +1647,11 @@ files:
1647
1647
  - app/components/coco/messaging/notice/notice.html.erb
1648
1648
  - app/components/coco/messaging/notice/notice.js
1649
1649
  - app/components/coco/messaging/notice/notice.rb
1650
+ - app/components/coco/messaging/popover/popover.css
1651
+ - app/components/coco/messaging/popover/popover.html.erb
1652
+ - app/components/coco/messaging/popover/popover.js
1653
+ - app/components/coco/messaging/popover/popover.rb
1654
+ - app/components/coco/messaging/popover/popover_content.js
1650
1655
  - app/components/coco/messaging/snackbar/snackbar.css
1651
1656
  - app/components/coco/messaging/snackbar/snackbar.html.erb
1652
1657
  - app/components/coco/messaging/snackbar/snackbar.js