@operato/event-view 10.29.71 → 10.29.79

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.
@@ -0,0 +1,84 @@
1
+ import { html, fixture, expect } from '@open-wc/testing'
2
+
3
+ import '../src/ox-event-view.js'
4
+ import { OxEventView } from '../src/ox-event-view.js'
5
+ import { CALENDAR, EventProvider } from '../src/types.js'
6
+
7
+ /**
8
+ * The calendar theme that @operato/styles ships reads in the dark theme.
9
+ *
10
+ * Its event chips sat on a fixed #f4f4f4 while their text followed the theme, so with `.dark`
11
+ * on the body every chip was light text on a light bar. The cell rules were black at 10%,
12
+ * which does not show on a dark cell.
13
+ *
14
+ * The test loads the published theme files as an app would and measures what is drawn.
15
+ */
16
+
17
+ /* The styles package sits next to this one; the test server reaches it one level up. */
18
+ const THEMES = '/__wds-outside-root__/1/styles/themes/'
19
+
20
+ function luminance([r, g, b]: number[]) {
21
+ const f = (v: number) => ((v /= 255) <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4))
22
+ return 0.2126 * f(r) + 0.7152 * f(g) + 0.0722 * f(b)
23
+ }
24
+
25
+ function rgb(color: string) {
26
+ return color.match(/[\d.]+/g)!.slice(0, 3).map(Number)
27
+ }
28
+
29
+ function contrast(a: string, b: string) {
30
+ const [x, y] = [luminance(rgb(a)), luminance(rgb(b))]
31
+ return (Math.max(x, y) + 0.05) / (Math.min(x, y) + 0.05)
32
+ }
33
+
34
+ const provider: EventProvider = {
35
+ async fetchEventsForCalendar(calendar: CALENDAR) {
36
+ return new Map([[calendar[3].date, [{ title: 'chip', color: '#888' }]]])
37
+ }
38
+ }
39
+
40
+ const links: HTMLLinkElement[] = []
41
+
42
+ before(async () => {
43
+ for (const name of ['dark.css', 'calendar-theme.css']) {
44
+ const link = document.createElement('link')
45
+ link.rel = 'stylesheet'
46
+ link.href = THEMES + name
47
+ document.head.append(link)
48
+ links.push(link)
49
+ await new Promise((resolve, reject) => ((link.onload = resolve), (link.onerror = reject)))
50
+ }
51
+ document.body.classList.add('dark')
52
+ })
53
+
54
+ after(() => {
55
+ links.forEach(link => link.remove())
56
+ document.body.classList.remove('dark')
57
+ })
58
+
59
+ for (const mode of ['monthly', 'weekly'] as const) {
60
+ describe(`${mode} calendar in the dark theme`, () => {
61
+ it('an event chip is readable on its own background', async () => {
62
+ const el = (await fixture(html`<ox-event-view mode=${mode}></ox-event-view>`)) as OxEventView
63
+ el.eventProvider = provider
64
+ await new Promise(resolve => setTimeout(resolve, 100))
65
+
66
+ const view = el.renderRoot.querySelector(mode === 'monthly' ? 'calendar-monthly' : 'calendar-weekly')!
67
+ const chip = view.shadowRoot!.querySelector('[event]') as HTMLElement
68
+ expect(chip, 'the chip is drawn').to.exist
69
+
70
+ const style = getComputedStyle(chip)
71
+ expect(contrast(style.color, style.backgroundColor)).to.be.at.least(4.5)
72
+ })
73
+
74
+ it('the cell rules follow the theme outline', async () => {
75
+ const el = (await fixture(html`<ox-event-view mode=${mode}></ox-event-view>`)) as OxEventView
76
+ await el.updateComplete
77
+ const view = el.renderRoot.querySelector(mode === 'monthly' ? 'calendar-monthly' : 'calendar-weekly')!
78
+ const cell = view.shadowRoot!.querySelector('li[date]') as HTMLElement
79
+ const outline = getComputedStyle(document.body).getPropertyValue('--md-sys-color-outline-variant').trim()
80
+
81
+ expect(rgb(getComputedStyle(cell).borderRightColor)).to.deep.equal(rgb(outline))
82
+ })
83
+ })
84
+ }
@@ -0,0 +1,62 @@
1
+ import { html, fixture, expect } from '@open-wc/testing'
2
+
3
+ import '../src/ox-event-view.js'
4
+ import { OxEventView } from '../src/ox-event-view.js'
5
+
6
+ /**
7
+ * A calendar picks dates only when the host says it is a picker.
8
+ *
9
+ * Every calendar used to take a press or drag over its days as a range selection, and set
10
+ * touch-action: none on them so the browser would not read the drag as a scroll. On a phone that
11
+ * left screens which only show a calendar unable to scroll past it.
12
+ */
13
+
14
+ async function grid(mode: 'monthly' | 'weekly', selectable: boolean) {
15
+ const el = (await fixture(
16
+ html`<ox-event-view mode=${mode} ?selectable=${selectable}></ox-event-view>`
17
+ )) as OxEventView
18
+ await el.updateComplete
19
+ await new Promise(resolve => setTimeout(resolve, 50))
20
+
21
+ const view = el.renderRoot.querySelector(mode === 'monthly' ? 'calendar-monthly' : 'calendar-weekly')!
22
+ const days = Array.from(view.shadowRoot!.querySelectorAll('li[date]')) as HTMLElement[]
23
+ return { el, days }
24
+ }
25
+
26
+ function drag(from: HTMLElement, to: HTMLElement) {
27
+ const init = { bubbles: true, composed: true, cancelable: true, pointerId: 1, pointerType: 'touch' }
28
+ const down = new PointerEvent('pointerdown', init)
29
+ from.dispatchEvent(down)
30
+ to.dispatchEvent(new PointerEvent('pointermove', init))
31
+ to.dispatchEvent(new PointerEvent('pointerup', init))
32
+ return down
33
+ }
34
+
35
+ for (const mode of ['monthly', 'weekly'] as const) {
36
+ describe(`${mode} calendar selection`, () => {
37
+ it('a calendar that only shows leaves touch to the page and selects nothing', async () => {
38
+ const { el, days } = await grid(mode, false)
39
+ let selected = 0
40
+ el.addEventListener('select-date', () => selected++)
41
+
42
+ expect(getComputedStyle(days[1]).touchAction).to.equal('auto')
43
+
44
+ const down = drag(days[1], days[3])
45
+ expect(down.defaultPrevented).to.be.false
46
+ expect(selected).to.equal(0)
47
+ expect(days.some(day => day.hasAttribute('selected'))).to.be.false
48
+ })
49
+
50
+ it('a picker takes touch and reports the dragged range', async () => {
51
+ const { el, days } = await grid(mode, true)
52
+ let detail: Date[] | undefined
53
+ el.addEventListener('select-date', e => (detail = (e as CustomEvent).detail))
54
+
55
+ expect(getComputedStyle(days[1]).touchAction).to.equal('none')
56
+
57
+ const down = drag(days[3], days[1])
58
+ expect(down.defaultPrevented).to.be.true
59
+ expect(detail).to.deep.equal([(days[1] as any).date, (days[3] as any).date])
60
+ })
61
+ })
62
+ }
@@ -3,7 +3,7 @@ body {
3
3
 
4
4
  /* monthly common color */
5
5
  --calendar-monthly-text-color: var(--md-sys-color-secondary);
6
- --calendar-monthly-border: 1px solid rgba(0, 0, 0, 0.1);
6
+ --calendar-monthly-border: 1px solid var(--md-sys-color-outline-variant);
7
7
  --calendar-monthly-border-width: 0 1px 1px 0px;
8
8
 
9
9
  /* monthly layout */
@@ -21,16 +21,17 @@ body {
21
21
  --calendar-monthly-date-label-color: var(--md-sys-color-on-primary);
22
22
  --calendar-monthly-date-min-height: 120px;
23
23
 
24
- --calendar-monthly-background-color: #f4f4f4;
24
+ --calendar-monthly-background-color: var(--md-sys-color-surface-container-low);
25
+ --calendar-monthly-color: var(--md-sys-color-on-surface);
25
26
  --calendar-monthly-event-border-radius: var(--border-radius);
26
27
  --calendar-monthly-event-margin: var(--padding-narrow) 0 0 0;
27
28
  --calendar-monthly-event-padding: 2px var(--padding-default);
28
- --calendar-monthly-event-border: 3px solid #ccc;
29
+ --calendar-monthly-event-border: 3px solid var(--md-sys-color-outline);
29
30
  --calendar-monthly-event-border-width: 0 0 0 3px;
30
31
 
31
32
  /* weekly common color */
32
33
  --calendar-weekly-text-color: var(--md-sys-color-secondary);
33
- --calendar-weekly-border: 1px solid rgba(0, 0, 0, 0.1);
34
+ --calendar-weekly-border: 1px solid var(--md-sys-color-outline-variant);
34
35
  --calendar-weekly-border-width: 0 1px 1px 0px;
35
36
 
36
37
  /* weekly layout */
@@ -47,11 +48,11 @@ body {
47
48
  --calendar-weekly-date-label-padding: 0px 6px;
48
49
  --calendar-weekly-date-label-color: var(--md-sys-color-on-primary);
49
50
 
50
- --calendar-weekly-background-color: #f4f4f4;
51
+ --calendar-weekly-background-color: var(--md-sys-color-surface-container-low);
51
52
  --calendar-weekly-event-border-radius: var(--border-radius);
52
53
  --calendar-weekly-event-margin: var(--padding-narrow) 0 0 0;
53
54
  --calendar-weekly-event-padding: 2px var(--padding-default);
54
- --calendar-weekly-event-border: 3px solid #ccc;
55
+ --calendar-weekly-event-border: 3px solid var(--md-sys-color-outline);
55
56
  --calendar-weekly-event-border-width: 0 0 0 3px;
56
57
  }
57
58