@jsenv/core 29.8.6 → 29.9.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/README.md +1 -1
  2. package/dist/js/autoreload.js +1 -1
  3. package/dist/main.js +50 -2085
  4. package/package.json +2 -2
  5. package/src/build/build.js +33 -33
  6. package/src/plugins/plugins.js +1 -1
  7. package/src/plugins/ribbon/jsenv_plugin_ribbon.js +6 -1
  8. package/src/plugins/url_resolution/jsenv_plugin_url_resolution.js +6 -2
  9. package/src/plugins/url_resolution/node_esm_resolver.js +6 -1
  10. package/dist/js/html_src_set.js +0 -20
  11. package/src/plugins/toolbar/client/animation/toolbar_animation.js +0 -39
  12. package/src/plugins/toolbar/client/eventsource/eventsource.css +0 -83
  13. package/src/plugins/toolbar/client/eventsource/toolbar_eventsource.js +0 -57
  14. package/src/plugins/toolbar/client/execution/execution.css +0 -79
  15. package/src/plugins/toolbar/client/execution/toolbar_execution.js +0 -88
  16. package/src/plugins/toolbar/client/focus/focus.css +0 -61
  17. package/src/plugins/toolbar/client/focus/toolbar_focus.js +0 -19
  18. package/src/plugins/toolbar/client/jsenv_logo.svg +0 -140
  19. package/src/plugins/toolbar/client/notification/toolbar_notification.js +0 -181
  20. package/src/plugins/toolbar/client/responsive/overflow_menu.css +0 -61
  21. package/src/plugins/toolbar/client/responsive/toolbar_responsive.js +0 -103
  22. package/src/plugins/toolbar/client/settings/settings.css +0 -201
  23. package/src/plugins/toolbar/client/settings/toolbar_settings.js +0 -47
  24. package/src/plugins/toolbar/client/theme/jsenv_theme.css +0 -77
  25. package/src/plugins/toolbar/client/theme/light_theme.css +0 -106
  26. package/src/plugins/toolbar/client/theme/toolbar_theme.js +0 -34
  27. package/src/plugins/toolbar/client/toolbar.html +0 -457
  28. package/src/plugins/toolbar/client/toolbar_injector.js +0 -218
  29. package/src/plugins/toolbar/client/toolbar_main.css +0 -172
  30. package/src/plugins/toolbar/client/toolbar_main.js +0 -197
  31. package/src/plugins/toolbar/client/tooltip/tooltip.css +0 -61
  32. package/src/plugins/toolbar/client/tooltip/tooltip.js +0 -39
  33. package/src/plugins/toolbar/client/util/animation.js +0 -305
  34. package/src/plugins/toolbar/client/util/dom.js +0 -108
  35. package/src/plugins/toolbar/client/util/fetch_using_xhr.js +0 -400
  36. package/src/plugins/toolbar/client/util/fetching.js +0 -14
  37. package/src/plugins/toolbar/client/util/iframe_to_parent_href.js +0 -10
  38. package/src/plugins/toolbar/client/util/jsenv_logger.js +0 -28
  39. package/src/plugins/toolbar/client/util/preferences.js +0 -10
  40. package/src/plugins/toolbar/client/util/responsive.js +0 -112
  41. package/src/plugins/toolbar/client/util/util.js +0 -19
  42. package/src/plugins/toolbar/client/variant/variant.js +0 -74
  43. package/src/plugins/toolbar/jsenv_plugin_toolbar.js +0 -62
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/core",
3
- "version": "29.8.6",
3
+ "version": "29.9.0",
4
4
  "description": "Tool to develop, test and build js projects",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -73,7 +73,7 @@
73
73
  "@jsenv/importmap": "1.2.1",
74
74
  "@jsenv/integrity": "0.0.1",
75
75
  "@jsenv/log": "3.3.1",
76
- "@jsenv/node-esm-resolution": "1.0.0",
76
+ "@jsenv/node-esm-resolution": "1.0.1",
77
77
  "@jsenv/server": "14.1.10",
78
78
  "@jsenv/sourcemap": "1.0.7",
79
79
  "@jsenv/uneval": "1.6.0",
@@ -669,43 +669,43 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
669
669
  }
670
670
  if (rawUrlInfo.isEntryPoint) {
671
671
  addToBundlerIfAny(rawUrlInfo)
672
- if (rawUrlInfo.type === "html") {
673
- rawUrlInfo.dependencies.forEach((dependencyUrl) => {
674
- const dependencyUrlInfo = rawGraph.getUrlInfo(dependencyUrl)
675
- if (dependencyUrlInfo.isInline) {
676
- if (dependencyUrlInfo.type === "js_module") {
677
- // bundle inline script type module deps
678
- dependencyUrlInfo.references.forEach((inlineScriptRef) => {
679
- if (inlineScriptRef.type === "js_import") {
680
- const inlineUrlInfo = rawGraph.getUrlInfo(
681
- inlineScriptRef.url,
682
- )
683
- addToBundlerIfAny(inlineUrlInfo)
684
- }
685
- })
686
- }
687
- // inline content cannot be bundled
688
- return
672
+ }
673
+ if (rawUrlInfo.type === "html") {
674
+ rawUrlInfo.dependencies.forEach((dependencyUrl) => {
675
+ const dependencyUrlInfo = rawGraph.getUrlInfo(dependencyUrl)
676
+ if (dependencyUrlInfo.isInline) {
677
+ if (dependencyUrlInfo.type === "js_module") {
678
+ // bundle inline script type module deps
679
+ dependencyUrlInfo.references.forEach((inlineScriptRef) => {
680
+ if (inlineScriptRef.type === "js_import") {
681
+ const inlineUrlInfo = rawGraph.getUrlInfo(
682
+ inlineScriptRef.url,
683
+ )
684
+ addToBundlerIfAny(inlineUrlInfo)
685
+ }
686
+ })
689
687
  }
690
- addToBundlerIfAny(dependencyUrlInfo)
691
- })
692
- rawUrlInfo.references.forEach((reference) => {
688
+ // inline content cannot be bundled
689
+ return
690
+ }
691
+ addToBundlerIfAny(dependencyUrlInfo)
692
+ })
693
+ rawUrlInfo.references.forEach((reference) => {
694
+ if (
695
+ reference.isResourceHint &&
696
+ reference.expectedType === "js_module"
697
+ ) {
698
+ const referencedUrlInfo = rawGraph.getUrlInfo(reference.url)
693
699
  if (
694
- reference.isResourceHint &&
695
- reference.expectedType === "js_module"
700
+ referencedUrlInfo &&
701
+ // something else than the resource hint is using this url
702
+ referencedUrlInfo.dependents.size > 0
696
703
  ) {
697
- const referencedUrlInfo = rawGraph.getUrlInfo(reference.url)
698
- if (
699
- referencedUrlInfo &&
700
- // something else than the resource hint is using this url
701
- referencedUrlInfo.dependents.size > 0
702
- ) {
703
- addToBundlerIfAny(referencedUrlInfo)
704
- }
704
+ addToBundlerIfAny(referencedUrlInfo)
705
705
  }
706
- })
707
- return
708
- }
706
+ }
707
+ })
708
+ return
709
709
  }
710
710
  // File referenced with new URL('./file.js', import.meta.url)
711
711
  // are entry points that should be bundled
@@ -83,8 +83,8 @@ export const getCorePlugins = ({
83
83
  jsenvPluginHttpUrls(),
84
84
  jsenvPluginUrlResolution({
85
85
  runtimeCompat,
86
- urlResolution,
87
86
  clientMainFileUrl,
87
+ urlResolution,
88
88
  }),
89
89
  jsenvPluginUrlVersion(),
90
90
  jsenvPluginCommonJsGlobals(),
@@ -14,7 +14,9 @@ export const jsenvPluginRibbon = ({
14
14
  const ribbonClientFileUrl = new URL("./client/ribbon.js", import.meta.url)
15
15
  const associations = URL_META.resolveAssociations(
16
16
  {
17
- ribbon: { [htmlInclude]: true },
17
+ ribbon: {
18
+ [htmlInclude]: true,
19
+ },
18
20
  },
19
21
  rootDirectoryUrl,
20
22
  )
@@ -23,6 +25,9 @@ export const jsenvPluginRibbon = ({
23
25
  appliesDuring: "dev",
24
26
  transformUrlContent: {
25
27
  html: (urlInfo, context) => {
28
+ if (urlInfo.data.noribbon) {
29
+ return null
30
+ }
26
31
  const { ribbon } = URL_META.applyAssociations({
27
32
  url: asUrlWithoutSearch(urlInfo.url),
28
33
  associations,
@@ -70,10 +70,11 @@ export const jsenvPluginUrlResolution = ({
70
70
  }
71
71
  if (node_esm) {
72
72
  if (node_esm === true) node_esm = {}
73
- const { packageConditions } = node_esm
73
+ const { packageConditions, preservesSymlink } = node_esm
74
74
  resolvers[urlType] = createNodeEsmResolver({
75
75
  runtimeCompat,
76
76
  packageConditions,
77
+ preservesSymlink,
77
78
  })
78
79
  } else if (web) {
79
80
  resolvers[urlType] = resolveUrlUsingWebResolution
@@ -81,7 +82,10 @@ export const jsenvPluginUrlResolution = ({
81
82
  })
82
83
 
83
84
  if (!resolvers.js_module) {
84
- resolvers.js_module = createNodeEsmResolver({ runtimeCompat })
85
+ resolvers.js_module = createNodeEsmResolver({
86
+ runtimeCompat,
87
+ preservesSymlink: true,
88
+ })
85
89
  }
86
90
  if (!resolvers["*"]) {
87
91
  resolvers["*"] = resolveUrlUsingWebResolution
@@ -16,7 +16,11 @@ import {
16
16
  defaultReadPackageJson,
17
17
  } from "@jsenv/node-esm-resolution"
18
18
 
19
- export const createNodeEsmResolver = ({ runtimeCompat, packageConditions }) => {
19
+ export const createNodeEsmResolver = ({
20
+ runtimeCompat,
21
+ packageConditions,
22
+ preservesSymlink,
23
+ }) => {
20
24
  const nodeRuntimeEnabled = Object.keys(runtimeCompat).includes("node")
21
25
  // https://nodejs.org/api/esm.html#resolver-algorithm-specification
22
26
  packageConditions = packageConditions || [
@@ -37,6 +41,7 @@ export const createNodeEsmResolver = ({ runtimeCompat, packageConditions }) => {
37
41
  conditions: packageConditions,
38
42
  parentUrl,
39
43
  specifier: reference.specifier,
44
+ preservesSymlink,
40
45
  })
41
46
  if (context.dev) {
42
47
  const dependsOnPackageJson =
@@ -1,20 +0,0 @@
1
- const parseSrcSet = srcset => {
2
- const srcCandidates = [];
3
- srcset.split(",").forEach(set => {
4
- const [specifier, descriptor] = set.trim().split(" ");
5
- srcCandidates.push({
6
- specifier,
7
- descriptor
8
- });
9
- });
10
- return srcCandidates;
11
- };
12
- const stringifySrcSet = srcCandidates => {
13
- const srcset = srcCandidates.map(({
14
- specifier,
15
- descriptor
16
- }) => `${specifier} ${descriptor}`).join(", ");
17
- return srcset;
18
- };
19
-
20
- export { parseSrcSet as p, stringifySrcSet as s };
@@ -1,39 +0,0 @@
1
- import { createPreference } from "../util/preferences.js"
2
-
3
- const animationPreference = createPreference("animation")
4
-
5
- export const renderToolbarAnimation = () => {
6
- const animCheckbox = document.querySelector("#toggle-anims")
7
- animCheckbox.checked = getAnimationPreference()
8
- animCheckbox.onchange = () => {
9
- setAnimationPreference(animCheckbox.checked)
10
- onPreferenceChange(animCheckbox.checked)
11
- }
12
- onPreferenceChange()
13
-
14
- // enable toolbar transition only after first render
15
- setTimeout(() => {
16
- document.querySelector("#toolbar").setAttribute("data-animate", "")
17
- })
18
- }
19
-
20
- const onPreferenceChange = (value = getAnimationPreference()) => {
21
- if (value) {
22
- enableAnimation()
23
- } else {
24
- disableAnimation()
25
- }
26
- }
27
-
28
- const getAnimationPreference = () =>
29
- animationPreference.has() ? animationPreference.get() : true
30
-
31
- const setAnimationPreference = (value) => animationPreference.set(value)
32
-
33
- const enableAnimation = () => {
34
- document.documentElement.removeAttribute("data-animation-disabled")
35
- }
36
-
37
- const disableAnimation = () => {
38
- document.documentElement.setAttribute("data-animation-disabled", "")
39
- }
@@ -1,83 +0,0 @@
1
- #eventsource-indicator button {
2
- position: relative;
3
- }
4
-
5
- #eventsource-indicator button svg {
6
- width: 40px;
7
- height: 40px;
8
- }
9
-
10
- #eventsource-indicator .event-source-autoreload {
11
- position: absolute;
12
- width: 32px;
13
- height: 32px;
14
- margin: 4px;
15
- left: 0;
16
- top: 0;
17
- }
18
-
19
- .event-source-autoreload[data-variant="enabled"] {
20
- color: green;
21
- }
22
-
23
- #eventsource-indicator .event-source-icon {
24
- width: 40px;
25
- height: 40px;
26
- }
27
-
28
- .eventsource-circle {
29
- stroke: black;
30
- stroke-width: 0;
31
- }
32
-
33
- .eventsource-circle[data-variant="off"] {
34
- fill: #cecece;
35
- }
36
-
37
- .eventsource-circle[data-variant="connecting"] {
38
- fill: #cecece;
39
- animation: wink 1.2s ease-out infinite;
40
- transform-origin: center;
41
- }
42
-
43
- @keyframes wink {
44
- 0% {
45
- opacity: 0;
46
- }
47
- 80% {
48
- opacity: 1;
49
- }
50
- 100% {
51
- opacity: 0;
52
- }
53
- }
54
-
55
- .eventsource-ring {
56
- stroke: rgba(206, 206, 206, 0.46);
57
- stroke-width: 4;
58
- fill: transparent;
59
- animation: pulse 1.2s ease-out infinite;
60
- transform-origin: center;
61
- }
62
-
63
- @keyframes pulse {
64
- 0% {
65
- transform: scale(0);
66
- opacity: 0;
67
- }
68
- 50% {
69
- opacity: 1;
70
- }
71
- 100% {
72
- transform: scale(1);
73
- opacity: 0;
74
- }
75
- }
76
-
77
- .eventsource-circle[data-variant="connected"] {
78
- fill: green;
79
- }
80
-
81
- .eventsource-circle[data-variant="failed"] {
82
- fill: #cc0000;
83
- }
@@ -1,57 +0,0 @@
1
- import { removeForceHideElement } from "../util/dom.js"
2
- import { enableVariant } from "../variant/variant.js"
3
- import {
4
- toggleTooltip,
5
- removeAutoShowTooltip,
6
- autoShowTooltip,
7
- } from "../tooltip/tooltip.js"
8
-
9
- const parentEventSourceClient = window.parent.__jsenv_event_source_client__
10
-
11
- export const initToolbarEventSource = () => {
12
- removeForceHideElement(document.querySelector("#eventsource-indicator"))
13
- if (!parentEventSourceClient) {
14
- disableAutoreloadSetting()
15
- return
16
- }
17
- parentEventSourceClient.status.onchange = () => {
18
- updateEventSourceIndicator()
19
- }
20
- updateEventSourceIndicator()
21
- }
22
-
23
- const updateEventSourceIndicator = () => {
24
- const eventSourceIndicator = document.querySelector("#eventsource-indicator")
25
- const eventSourceConnectionState = parentEventSourceClient.status.value
26
- enableVariant(eventSourceIndicator, {
27
- eventsource: eventSourceConnectionState,
28
- })
29
- const variantNode = document.querySelector(
30
- "#eventsource-indicator > [data-when-active]",
31
- )
32
- variantNode.querySelector("button").onclick = () => {
33
- toggleTooltip(eventSourceIndicator)
34
- }
35
- if (eventSourceConnectionState === "connecting") {
36
- variantNode.querySelector("a").onclick = () => {
37
- parentEventSourceClient.disconnect()
38
- }
39
- } else if (eventSourceConnectionState === "connected") {
40
- removeAutoShowTooltip(eventSourceIndicator)
41
- } else if (eventSourceConnectionState === "disconnected") {
42
- autoShowTooltip(eventSourceIndicator)
43
- variantNode.querySelector("a").onclick = () => {
44
- parentEventSourceClient.connect()
45
- }
46
- }
47
- }
48
-
49
- const disableAutoreloadSetting = () => {
50
- document
51
- .querySelector(".settings-autoreload")
52
- .setAttribute("data-disabled", "true")
53
- document
54
- .querySelector(".settings-autoreload")
55
- .setAttribute("title", `Autoreload not available: disabled by server`)
56
- document.querySelector("#toggle-autoreload").disabled = true
57
- }
@@ -1,79 +0,0 @@
1
- /* Loader icon */
2
- #loader-icon {
3
- width: 20px;
4
- height: 20px;
5
- margin: 10px;
6
- transform: scaleX(-1);
7
- color: #cecece;
8
- }
9
- #loader-icon[data-animate] {
10
- opacity: 0;
11
- transform-origin: center;
12
- animation: rotateLoader 1s linear infinite !important;
13
- }
14
- @keyframes rotateLoader {
15
- 0% {
16
- transform: scaleX(-1) rotate(360deg);
17
- opacity: 1;
18
- }
19
- 50% {
20
- opacity: 0;
21
- }
22
- 100% {
23
- transform: scaleX(-1) rotate(0deg);
24
- opacity: 1;
25
- }
26
- }
27
-
28
- /* Check icon */
29
- #check-icon {
30
- width: 25px;
31
- height: 25px;
32
- margin: 7px;
33
- opacity: 0;
34
- stroke-width: 5;
35
- }
36
- #check-icon[data-animate] {
37
- opacity: 1;
38
- }
39
- #check-icon[data-animate] path {
40
- transform-origin: 50% 50%;
41
- stroke-dasharray: 48;
42
- stroke-dashoffset: 48;
43
- animation: stroke 0.5s cubic-bezier(0.65, 0, 0.45, 1) forwards;
44
- stroke: green;
45
- }
46
- @keyframes stroke {
47
- 100% {
48
- stroke-dashoffset: 0;
49
- }
50
- }
51
-
52
- /* Cross icon */
53
- #cross-icon {
54
- width: 20px;
55
- height: 20px;
56
- margin: 10px;
57
- opacity: 0;
58
- stroke-width: 5;
59
- }
60
- #cross-icon rect {
61
- width: 33px;
62
- height: 0;
63
- fill: #d74640;
64
- }
65
- #cross-icon[data-animate] {
66
- opacity: 1;
67
- }
68
- #cross-icon[data-animate] #cross_p1 {
69
- animation: draw 0.5s cubic-bezier(0.65, 0, 0.45, 1) forwards;
70
- }
71
- #cross-icon[data-animate] #cross_p2 {
72
- animation: draw 0.5s cubic-bezier(0.65, 0, 0.45, 1) forwards 0.2s;
73
- }
74
- @keyframes draw {
75
- 100% {
76
- height: 376.964px;
77
- width: 45px;
78
- }
79
- }
@@ -1,88 +0,0 @@
1
- import { removeForceHideElement } from "../util/dom.js"
2
- import { enableVariant } from "../variant/variant.js"
3
- import { toggleTooltip } from "../tooltip/tooltip.js"
4
- import { notifyExecutionResult } from "../notification/toolbar_notification.js"
5
-
6
- export const renderExecutionInToolbar = async () => {
7
- // reset file execution indicator ui
8
- applyExecutionIndicator()
9
- removeForceHideElement(document.querySelector("#execution-indicator"))
10
-
11
- const { status, startTime, endTime } =
12
- await window.parent.__supervisor__.getDocumentExecutionResult()
13
- const execution = { status, startTime, endTime }
14
- applyExecutionIndicator(execution)
15
- const executionStorageKey = window.location.href
16
- const previousExecution = sessionStorage.hasOwnProperty(executionStorageKey)
17
- ? JSON.parse(sessionStorage.getItem(executionStorageKey))
18
- : undefined
19
- notifyExecutionResult(executionStorageKey, execution, previousExecution)
20
- sessionStorage.setItem(executionStorageKey, JSON.stringify(execution))
21
- }
22
-
23
- // const changeLink = variantNode.querySelector(".eventsource-changes-link")
24
- // changeLink.innerHTML = reloadMessageCount
25
- // changeLink.onclick = () => {
26
- // console.log(reloadMessages)
27
- // // eslint-disable-next-line no-alert
28
- // window.parent.alert(JSON.stringify(reloadMessages, null, " "))
29
- // }
30
-
31
- // const someFailed = reloadMessages.some((m) => m.status === "failed")
32
- // const somePending = reloadMessages.some((m) => m.status === "pending")
33
- // const applyLink = variantNode.querySelector(".eventsource-reload-link")
34
- // applyLink.innerHTML = someFailed
35
- // ? "failed"
36
- // : somePending
37
- // ? "applying..."
38
- // : "apply changes"
39
- // applyLink.onclick = someFailed
40
- // ? () => {
41
- // parentEventSourceClient.applyReloadMessageEffects()
42
- // }
43
- // : somePending
44
- // ? () => {}
45
- // : () => {
46
- // parentEventSourceClient.applyReloadMessageEffects()
47
- // }
48
-
49
- // parentEventSourceClient.reloadMessagesSignal.onchange = () => {
50
- // updateEventSourceIndicator()
51
- // }
52
- // const autoreloadCheckbox = document.querySelector("#toggle-autoreload")
53
- // autoreloadCheckbox.checked = parentEventSourceClient.isAutoreloadEnabled()
54
- // autoreloadCheckbox.onchange = () => {
55
- // parentEventSourceClient.setAutoreloadPreference(autoreloadCheckbox.checked)
56
- // updateEventSourceIndicator()
57
- // }
58
-
59
- const applyExecutionIndicator = ({
60
- status = "running",
61
- startTime,
62
- endTime,
63
- } = {}) => {
64
- const executionIndicator = document.querySelector("#execution-indicator")
65
- enableVariant(executionIndicator, { execution: status })
66
- const variantNode = executionIndicator.querySelector("[data-when-active]")
67
- variantNode.querySelector("button").onclick = () =>
68
- toggleTooltip(executionIndicator)
69
- variantNode.querySelector(".tooltip").textContent = computeText({
70
- status,
71
- startTime,
72
- endTime,
73
- })
74
- }
75
-
76
- // relative time: https://github.com/tc39/proposal-intl-relative-time/issues/118
77
- const computeText = ({ status, startTime, endTime }) => {
78
- if (status === "completed") {
79
- return `Execution completed in ${endTime - startTime}ms`
80
- }
81
- if (status === "errored") {
82
- return `Execution failed in ${endTime - startTime}ms`
83
- }
84
- if (status === "running") {
85
- return "Executing..."
86
- }
87
- return ""
88
- }
@@ -1,61 +0,0 @@
1
- button:focus,
2
- a:focus,
3
- input:focus,
4
- *[data-contains-hidden-input] input:focus + * {
5
- outline-style: none;
6
- outline-offset: -2px;
7
- }
8
-
9
- *[data-contains-hidden-input] input:focus + * {
10
- outline-width: 4px;
11
- outline-offset: -2px;
12
- }
13
-
14
- html[data-last-interaction="keyboard"] button:focus,
15
- html[data-last-interaction="keyboard"] a:focus,
16
- html[data-last-interaction="keyboard"] input:focus,
17
- html[data-last-interaction="keyboard"]
18
- *[data-contains-hidden-input]
19
- input:focus
20
- + * {
21
- outline-style: auto;
22
- }
23
-
24
- html[data-last-interaction="keyboard"]
25
- *[data-contains-hidden-input]
26
- input:focus
27
- + * {
28
- outline-color: rgb(0, 150, 255);
29
- }
30
-
31
- /*
32
- Don't try to replace @-moz-document url-prefix() this by
33
-
34
- -moz-outline or -moz-outline-color
35
- Because firefox would take into account outline instead of -moz-outline
36
-
37
- :moz-focus-ring
38
- Because for some element we set the focus outline on a div which would not match :focusring
39
- */
40
- @-moz-document url-prefix() {
41
- html[data-last-interaction="keyboard"] button:focus,
42
- html[data-last-interaction="keyboard"] a:focus,
43
- html[data-last-interaction="keyboard"] input:focus,
44
- html[data-last-interaction="keyboard"]
45
- *[data-input-customized]
46
- input:focus
47
- + * {
48
- outline-width: 2px;
49
- outline-offset: 0;
50
- outline-style: solid;
51
- /*
52
- force a blue color for firefox otherwise
53
- it uses outline-color: inherit
54
- making it unpredictible and sometimes hard to see
55
- */
56
- outline-color: rgb(0, 150, 255);
57
- }
58
- }
59
- ::-moz-focus-inner {
60
- border: 0;
61
- }
@@ -1,19 +0,0 @@
1
- // handle data-last-interaction attr on html (focusring)
2
- window.addEventListener("mousedown", (mousedownEvent) => {
3
- if (mousedownEvent.defaultPrevented) {
4
- return
5
- }
6
- document.documentElement.setAttribute("data-last-interaction", "mouse")
7
- })
8
- window.addEventListener("touchstart", (touchstartEvent) => {
9
- if (touchstartEvent.defaultPrevented) {
10
- return
11
- }
12
- document.documentElement.setAttribute("data-last-interaction", "mouse")
13
- })
14
- window.addEventListener("keydown", (keydownEvent) => {
15
- if (keydownEvent.defaultPrevented) {
16
- return
17
- }
18
- document.documentElement.setAttribute("data-last-interaction", "keyboard")
19
- })