@atlaskit/primitives 2.0.3 → 2.1.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # @atlaskit/primitives
2
2
 
3
+ ## 2.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#74930](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/74930) [`707a8fee2aee`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/707a8fee2aee) - Both the Pressable and Anchor primitives (in Alpha) now support analytics tracking in the same fashion as `@atlaskit/button`. An additional prop `componentName` allows analytics to be configured if a parent component name is desired to be tracked rather than the primitive names. For the time being this tracking is opt-in via use of the `componentName` prop. This will be made default behavior in an upcoming release once tracking is removed in the new Buttons, and `@atlaskit/button` is bumped to use the latest version of `@atlaskit/primitives`
8
+ - [#75221](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/75221) [`c15d58bff276`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/c15d58bff276) - `Text` inherits color by default if `color` prop is not provided.
9
+ Removed auto-collapsing behaviour of `Text`
10
+
3
11
  ## 2.0.3
4
12
 
5
13
  ### Patch Changes
@@ -12,10 +12,13 @@ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers
12
12
  var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
13
13
  var _react = _interopRequireWildcard(require("react"));
14
14
  var _tinyInvariant = _interopRequireDefault(require("tiny-invariant"));
15
+ var _analyticsNext = require("@atlaskit/analytics-next");
15
16
  var _appProvider = require("@atlaskit/app-provider");
17
+ var _noop = _interopRequireDefault(require("@atlaskit/ds-lib/noop"));
18
+ var _interactionContext = _interopRequireDefault(require("@atlaskit/interaction-context"));
16
19
  var _xcss = require("../xcss/xcss");
17
20
  var _box = _interopRequireDefault(require("./box"));
18
- var _excluded = ["href", "children", "backgroundColor", "padding", "paddingBlock", "paddingBlockStart", "paddingBlockEnd", "paddingInline", "paddingInlineStart", "paddingInlineEnd", "testId", "xcss", "target", "rel"];
21
+ var _excluded = ["href", "children", "backgroundColor", "padding", "paddingBlock", "paddingBlockStart", "paddingBlockEnd", "paddingInline", "paddingInlineStart", "paddingInlineEnd", "testId", "xcss", "target", "rel", "onClick", "interactionName", "componentName", "analyticsContext"];
19
22
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
20
23
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof3(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
21
24
  // TODO: Duplicated FocusRing styles due to lack of `xcss` support
@@ -54,7 +57,26 @@ var Link = function Link(_ref, ref) {
54
57
  xcssStyles = _ref.xcss,
55
58
  target = _ref.target,
56
59
  rel = _ref.rel,
60
+ _ref$onClick = _ref.onClick,
61
+ providedOnClick = _ref$onClick === void 0 ? _noop.default : _ref$onClick,
62
+ interactionName = _ref.interactionName,
63
+ componentName = _ref.componentName,
64
+ analyticsContext = _ref.analyticsContext,
57
65
  htmlAttributes = (0, _objectWithoutProperties2.default)(_ref, _excluded);
66
+ var interactionContext = (0, _react.useContext)(_interactionContext.default);
67
+ var handleClick = (0, _react.useCallback)(function (e, analyticsEvent) {
68
+ interactionContext && interactionContext.tracePress(interactionName, e.timeStamp);
69
+ providedOnClick(e, analyticsEvent);
70
+ }, [providedOnClick, interactionContext, interactionName]);
71
+ var onClick = (0, _analyticsNext.usePlatformLeafEventHandler)({
72
+ fn: handleClick,
73
+ action: 'clicked',
74
+ componentName: componentName || 'Anchor',
75
+ packageName: "@atlaskit/primitives",
76
+ packageVersion: "2.1.0",
77
+ analyticsData: analyticsContext,
78
+ actionSubject: 'link'
79
+ });
58
80
  var RouterLink = (0, _appProvider.useRouterLink)();
59
81
 
60
82
  // Combine default styles with supplied styles. XCSS does not support deep nested arrays
@@ -91,6 +113,11 @@ var Link = function Link(_ref, ref) {
91
113
  paddingInline: paddingInline,
92
114
  paddingInlineStart: paddingInlineStart,
93
115
  paddingInlineEnd: paddingInlineEnd
116
+ // TODO: This only tracks events if componentName is supplied, which makes tracking opt-in during
117
+ // the transition period. This will be removed once `@atlaskit/button` is bumped to use the latest
118
+ // version of primitives
119
+ ,
120
+ onClick: componentName ? onClick : providedOnClick
94
121
  // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage
95
122
  ,
96
123
  xcss: styles
@@ -103,8 +130,9 @@ var Link = function Link(_ref, ref) {
103
130
  *
104
131
  * @internal Still under development. Do not use.
105
132
  *
106
- * A Link is a primitive component that renders an `<a>` anchor. It utilizes
107
- * the configured router link component in the AppProvider if set.
133
+ * Link is a primitive for building custom anchor links. It's a wrapper around the HTML `<a>` element that provides a consistent API for handling client-side routing and Atlassian Design System styling.
134
+ *
135
+ * This component is mostly used by other design system components, such as the [link component](/components/link/usage).
108
136
  *
109
137
  * - [Examples](https://atlassian.design/components/primitives/link/examples)
110
138
  * - [Code](https://atlassian.design/components/primitives/link/code)
@@ -10,9 +10,12 @@ var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")
10
10
  var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
11
11
  var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
12
12
  var _react = _interopRequireWildcard(require("react"));
13
+ var _analyticsNext = require("@atlaskit/analytics-next");
14
+ var _noop = _interopRequireDefault(require("@atlaskit/ds-lib/noop"));
15
+ var _interactionContext = _interopRequireDefault(require("@atlaskit/interaction-context"));
13
16
  var _xcss = require("../xcss/xcss");
14
17
  var _box = _interopRequireDefault(require("./box"));
15
- var _excluded = ["children", "backgroundColor", "padding", "paddingBlock", "paddingBlockStart", "paddingBlockEnd", "paddingInline", "paddingInlineStart", "paddingInlineEnd", "isDisabled", "type", "testId", "xcss"];
18
+ var _excluded = ["children", "backgroundColor", "padding", "paddingBlock", "paddingBlockStart", "paddingBlockEnd", "paddingInline", "paddingInlineStart", "paddingInlineEnd", "isDisabled", "type", "testId", "xcss", "onClick", "interactionName", "componentName", "analyticsContext"];
16
19
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
17
20
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
18
21
  // TODO: Duplicated FocusRing styles due to lack of `xcss` support
@@ -61,7 +64,27 @@ var UNSAFE_PRESSABLE = /*#__PURE__*/(0, _react.forwardRef)(function (_ref, ref)
61
64
  type = _ref$type === void 0 ? 'button' : _ref$type,
62
65
  testId = _ref.testId,
63
66
  xcssStyles = _ref.xcss,
67
+ _ref$onClick = _ref.onClick,
68
+ providedOnClick = _ref$onClick === void 0 ? _noop.default : _ref$onClick,
69
+ interactionName = _ref.interactionName,
70
+ componentName = _ref.componentName,
71
+ analyticsContext = _ref.analyticsContext,
64
72
  htmlAttributes = (0, _objectWithoutProperties2.default)(_ref, _excluded);
73
+ var interactionContext = (0, _react.useContext)(_interactionContext.default);
74
+ var handleClick = (0, _react.useCallback)(function (e, analyticsEvent) {
75
+ interactionContext && interactionContext.tracePress(interactionName, e.timeStamp);
76
+ providedOnClick(e, analyticsEvent);
77
+ }, [providedOnClick, interactionContext, interactionName]);
78
+ var onClick = (0, _analyticsNext.usePlatformLeafEventHandler)({
79
+ fn: handleClick,
80
+ action: 'clicked',
81
+ componentName: componentName || 'Pressable',
82
+ packageName: "@atlaskit/primitives",
83
+ packageVersion: "2.1.0",
84
+ analyticsData: analyticsContext,
85
+ actionSubject: 'button'
86
+ });
87
+
65
88
  // Combine default styles with supplied styles. XCSS does not support deep nested arrays
66
89
  var styles = [(0, _xcss.xcss)({
67
90
  cursor: isDisabled ? 'not-allowed' : 'pointer'
@@ -71,7 +94,12 @@ var UNSAFE_PRESSABLE = /*#__PURE__*/(0, _react.forwardRef)(function (_ref, ref)
71
94
  as: "button",
72
95
  ref: ref,
73
96
  testId: testId,
74
- type: type,
97
+ type: type
98
+ // TODO: This only tracks events if componentName is supplied, which makes tracking opt-in during
99
+ // the transition period. This will be removed once `@atlaskit/button` is bumped to use the latest
100
+ // version of primitives
101
+ ,
102
+ onClick: componentName ? onClick : providedOnClick,
75
103
  backgroundColor: backgroundColor,
76
104
  padding: padding,
77
105
  paddingBlock: paddingBlock,
@@ -7,8 +7,7 @@ Object.defineProperty(exports, "__esModule", {
7
7
  exports.default = void 0;
8
8
  var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
9
9
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
10
- var _react = require("react");
11
- var _react2 = require("@emotion/react");
10
+ var _react = require("@emotion/react");
12
11
  var _tinyInvariant = _interopRequireDefault(require("tiny-invariant"));
13
12
  var _styleMaps = require("../xcss/style-maps.partial");
14
13
  var _surfaceProvider = require("./internal/surface-provider");
@@ -19,34 +18,34 @@ var asAllowlist = ['span', 'p', 'strong', 'em'];
19
18
  // We're doing this because our CSS reset can add top margins to elements such as `p` which is totally insane.
20
19
  // Long term we should remove those instances from the reset - it should be a reset to 0.
21
20
  // For now, at least we know <Text> will be unaffected by this.
22
- var resetStyles = (0, _react2.css)({
21
+ var resetStyles = (0, _react.css)({
23
22
  margin: 0
24
23
  });
25
24
  var variantStyles = _objectSpread(_objectSpread({}, _styleMaps.bodyTextStylesMap), _styleMaps.uiTextStylesMap);
26
- var strongStyles = (0, _react2.css)({
25
+ var strongStyles = (0, _react.css)({
27
26
  fontWeight: 'bold'
28
27
  });
29
- var emStyles = (0, _react2.css)({
28
+ var emStyles = (0, _react.css)({
30
29
  fontStyle: 'italic'
31
30
  });
32
31
  var textAlignMap = {
33
- center: (0, _react2.css)({
32
+ center: (0, _react.css)({
34
33
  textAlign: 'center'
35
34
  }),
36
- end: (0, _react2.css)({
35
+ end: (0, _react.css)({
37
36
  textAlign: 'end'
38
37
  }),
39
- start: (0, _react2.css)({
38
+ start: (0, _react.css)({
40
39
  textAlign: 'start'
41
40
  })
42
41
  };
43
- var truncationStyles = (0, _react2.css)({
42
+ var truncationStyles = (0, _react.css)({
44
43
  display: '-webkit-box',
45
44
  overflow: 'hidden',
46
45
  WebkitBoxOrient: 'vertical'
47
46
  });
48
47
  var wordBreakMap = {
49
- breakAll: (0, _react2.css)({
48
+ breakAll: (0, _react.css)({
50
49
  wordBreak: 'break-all'
51
50
  })
52
51
  };
@@ -56,19 +55,14 @@ var wordBreakMap = {
56
55
  */
57
56
  var useColor = function useColor(colorProp) {
58
57
  var surface = (0, _surfaceProvider.useSurface)();
59
- var inverseTextColor = _styleMaps.inverseColorMap[surface];
60
58
 
61
59
  /**
62
60
  * Where the color of the surface is inverted we override the user choice
63
61
  * as there is no valid choice that is not covered by the override.
64
62
  */
65
- var color = inverseTextColor !== null && inverseTextColor !== void 0 ? inverseTextColor : colorProp;
63
+ var color = _styleMaps.inverseColorMap.hasOwnProperty(surface) ? _styleMaps.inverseColorMap[surface] : colorProp;
66
64
  return color;
67
65
  };
68
- var HasTextAncestorContext = /*#__PURE__*/(0, _react.createContext)(false);
69
- var useHasTextAncestor = function useHasTextAncestor() {
70
- return (0, _react.useContext)(HasTextAncestorContext);
71
- };
72
66
 
73
67
  /**
74
68
  * __Text__
@@ -83,8 +77,7 @@ var Text = function Text(_ref) {
83
77
  var children = _ref.children,
84
78
  props = (0, _objectWithoutProperties2.default)(_ref, _excluded);
85
79
  var asElement = props.as,
86
- _props$color = props.color,
87
- colorProp = _props$color === void 0 ? 'color.text' : _props$color,
80
+ colorProp = props.color,
88
81
  textAlign = props.textAlign,
89
82
  testId = props.testId,
90
83
  id = props.id,
@@ -103,16 +96,7 @@ var Text = function Text(_ref) {
103
96
  maxLines = props.maxLines;
104
97
  }
105
98
  var color = useColor(colorProp);
106
- var isWrapped = useHasTextAncestor();
107
-
108
- /**
109
- * If the text is already wrapped and applies no props we can just
110
- * render the children directly as a fragment.
111
- */
112
- if (isWrapped && Object.keys(props).length === 0) {
113
- return (0, _react2.jsx)(_react.Fragment, null, children);
114
- }
115
- var component = (0, _react2.jsx)(Component, {
99
+ return (0, _react.jsx)(Component, {
116
100
  css: [resetStyles, variant && variantStyles[variant], color && _styleMaps.textColorStylesMap[color], maxLines && truncationStyles, maxLines === 1 && wordBreakMap.breakAll, textAlign && textAlignMap[textAlign], weight && _styleMaps.fontWeightStylesMap[weight], asElement === 'em' && emStyles, asElement === 'strong' && strongStyles],
117
101
  style: {
118
102
  WebkitLineClamp: maxLines
@@ -120,10 +104,5 @@ var Text = function Text(_ref) {
120
104
  "data-testid": testId,
121
105
  id: id
122
106
  }, children);
123
- return isWrapped ?
124
- // no need to re-apply context if the text is already wrapped
125
- component : (0, _react2.jsx)(HasTextAncestorContext.Provider, {
126
- value: true
127
- }, component);
128
107
  };
129
108
  var _default = exports.default = Text;
package/dist/cjs/index.js CHANGED
@@ -52,6 +52,12 @@ Object.defineProperty(exports, "UNSAFE_BREAKPOINTS_CONFIG", {
52
52
  return _responsive.UNSAFE_BREAKPOINTS_CONFIG;
53
53
  }
54
54
  });
55
+ Object.defineProperty(exports, "UNSAFE_Pressable", {
56
+ enumerable: true,
57
+ get: function get() {
58
+ return _pressable.default;
59
+ }
60
+ });
55
61
  Object.defineProperty(exports, "UNSAFE_media", {
56
62
  enumerable: true,
57
63
  get: function get() {
@@ -84,4 +90,5 @@ var _flex = _interopRequireDefault(require("./components/flex"));
84
90
  var _grid = _interopRequireDefault(require("./components/grid"));
85
91
  var _bleed = _interopRequireDefault(require("./components/bleed"));
86
92
  var _text = _interopRequireDefault(require("./components/text"));
93
+ var _pressable = _interopRequireDefault(require("./components/pressable"));
87
94
  var _responsive = require("./responsive");
@@ -1,7 +1,10 @@
1
1
  import _extends from "@babel/runtime/helpers/extends";
2
- import React, { forwardRef } from 'react';
2
+ import React, { forwardRef, useCallback, useContext } from 'react';
3
3
  import invariant from 'tiny-invariant';
4
+ import { usePlatformLeafEventHandler } from '@atlaskit/analytics-next';
4
5
  import { useRouterLink } from '@atlaskit/app-provider';
6
+ import noop from '@atlaskit/ds-lib/noop';
7
+ import InteractionContext from '@atlaskit/interaction-context';
5
8
  import { xcss } from '../xcss/xcss';
6
9
  import Box from './box';
7
10
  // TODO: Duplicated FocusRing styles due to lack of `xcss` support
@@ -40,8 +43,26 @@ const Link = ({
40
43
  xcss: xcssStyles,
41
44
  target,
42
45
  rel,
46
+ onClick: providedOnClick = noop,
47
+ interactionName,
48
+ componentName,
49
+ analyticsContext,
43
50
  ...htmlAttributes
44
51
  }, ref) => {
52
+ const interactionContext = useContext(InteractionContext);
53
+ const handleClick = useCallback((e, analyticsEvent) => {
54
+ interactionContext && interactionContext.tracePress(interactionName, e.timeStamp);
55
+ providedOnClick(e, analyticsEvent);
56
+ }, [providedOnClick, interactionContext, interactionName]);
57
+ const onClick = usePlatformLeafEventHandler({
58
+ fn: handleClick,
59
+ action: 'clicked',
60
+ componentName: componentName || 'Anchor',
61
+ packageName: "@atlaskit/primitives",
62
+ packageVersion: "2.1.0",
63
+ analyticsData: analyticsContext,
64
+ actionSubject: 'link'
65
+ });
45
66
  const RouterLink = useRouterLink();
46
67
 
47
68
  // Combine default styles with supplied styles. XCSS does not support deep nested arrays
@@ -78,6 +99,11 @@ const Link = ({
78
99
  paddingInline: paddingInline,
79
100
  paddingInlineStart: paddingInlineStart,
80
101
  paddingInlineEnd: paddingInlineEnd
102
+ // TODO: This only tracks events if componentName is supplied, which makes tracking opt-in during
103
+ // the transition period. This will be removed once `@atlaskit/button` is bumped to use the latest
104
+ // version of primitives
105
+ ,
106
+ onClick: componentName ? onClick : providedOnClick
81
107
  // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage
82
108
  ,
83
109
  xcss: styles
@@ -90,8 +116,9 @@ const Link = ({
90
116
  *
91
117
  * @internal Still under development. Do not use.
92
118
  *
93
- * A Link is a primitive component that renders an `<a>` anchor. It utilizes
94
- * the configured router link component in the AppProvider if set.
119
+ * Link is a primitive for building custom anchor links. It's a wrapper around the HTML `<a>` element that provides a consistent API for handling client-side routing and Atlassian Design System styling.
120
+ *
121
+ * This component is mostly used by other design system components, such as the [link component](/components/link/usage).
95
122
  *
96
123
  * - [Examples](https://atlassian.design/components/primitives/link/examples)
97
124
  * - [Code](https://atlassian.design/components/primitives/link/code)
@@ -1,5 +1,8 @@
1
1
  import _extends from "@babel/runtime/helpers/extends";
2
- import React, { forwardRef } from 'react';
2
+ import React, { forwardRef, useCallback, useContext } from 'react';
3
+ import { usePlatformLeafEventHandler } from '@atlaskit/analytics-next';
4
+ import noop from '@atlaskit/ds-lib/noop';
5
+ import InteractionContext from '@atlaskit/interaction-context';
3
6
  import { xcss } from '../xcss/xcss';
4
7
  import Box from './box';
5
8
  // TODO: Duplicated FocusRing styles due to lack of `xcss` support
@@ -47,8 +50,27 @@ const UNSAFE_PRESSABLE = /*#__PURE__*/forwardRef(({
47
50
  type = 'button',
48
51
  testId,
49
52
  xcss: xcssStyles,
53
+ onClick: providedOnClick = noop,
54
+ interactionName,
55
+ componentName,
56
+ analyticsContext,
50
57
  ...htmlAttributes
51
58
  }, ref) => {
59
+ const interactionContext = useContext(InteractionContext);
60
+ const handleClick = useCallback((e, analyticsEvent) => {
61
+ interactionContext && interactionContext.tracePress(interactionName, e.timeStamp);
62
+ providedOnClick(e, analyticsEvent);
63
+ }, [providedOnClick, interactionContext, interactionName]);
64
+ const onClick = usePlatformLeafEventHandler({
65
+ fn: handleClick,
66
+ action: 'clicked',
67
+ componentName: componentName || 'Pressable',
68
+ packageName: "@atlaskit/primitives",
69
+ packageVersion: "2.1.0",
70
+ analyticsData: analyticsContext,
71
+ actionSubject: 'button'
72
+ });
73
+
52
74
  // Combine default styles with supplied styles. XCSS does not support deep nested arrays
53
75
  let styles = [xcss({
54
76
  cursor: isDisabled ? 'not-allowed' : 'pointer'
@@ -58,7 +80,12 @@ const UNSAFE_PRESSABLE = /*#__PURE__*/forwardRef(({
58
80
  as: "button",
59
81
  ref: ref,
60
82
  testId: testId,
61
- type: type,
83
+ type: type
84
+ // TODO: This only tracks events if componentName is supplied, which makes tracking opt-in during
85
+ // the transition period. This will be removed once `@atlaskit/button` is bumped to use the latest
86
+ // version of primitives
87
+ ,
88
+ onClick: componentName ? onClick : providedOnClick,
62
89
  backgroundColor: backgroundColor,
63
90
  padding: padding,
64
91
  paddingBlock: paddingBlock,
@@ -1,5 +1,5 @@
1
1
  /** @jsx jsx */
2
- import { createContext, Fragment, useContext } from 'react';
2
+
3
3
  import { css, jsx } from '@emotion/react';
4
4
  import invariant from 'tiny-invariant';
5
5
  import { bodyTextStylesMap, fontWeightStylesMap, inverseColorMap, textColorStylesMap, uiTextStylesMap } from '../xcss/style-maps.partial';
@@ -48,17 +48,14 @@ const wordBreakMap = {
48
48
  */
49
49
  const useColor = colorProp => {
50
50
  const surface = useSurface();
51
- const inverseTextColor = inverseColorMap[surface];
52
51
 
53
52
  /**
54
53
  * Where the color of the surface is inverted we override the user choice
55
54
  * as there is no valid choice that is not covered by the override.
56
55
  */
57
- const color = inverseTextColor !== null && inverseTextColor !== void 0 ? inverseTextColor : colorProp;
56
+ const color = inverseColorMap.hasOwnProperty(surface) ? inverseColorMap[surface] : colorProp;
58
57
  return color;
59
58
  };
60
- const HasTextAncestorContext = /*#__PURE__*/createContext(false);
61
- const useHasTextAncestor = () => useContext(HasTextAncestorContext);
62
59
 
63
60
  /**
64
61
  * __Text__
@@ -75,7 +72,7 @@ const Text = ({
75
72
  }) => {
76
73
  const {
77
74
  as: asElement,
78
- color: colorProp = 'color.text',
75
+ color: colorProp,
79
76
  textAlign,
80
77
  testId,
81
78
  id,
@@ -94,16 +91,7 @@ const Text = ({
94
91
  maxLines = props.maxLines;
95
92
  }
96
93
  const color = useColor(colorProp);
97
- const isWrapped = useHasTextAncestor();
98
-
99
- /**
100
- * If the text is already wrapped and applies no props we can just
101
- * render the children directly as a fragment.
102
- */
103
- if (isWrapped && Object.keys(props).length === 0) {
104
- return jsx(Fragment, null, children);
105
- }
106
- const component = jsx(Component, {
94
+ return jsx(Component, {
107
95
  css: [resetStyles, variant && variantStyles[variant], color && textColorStylesMap[color], maxLines && truncationStyles, maxLines === 1 && wordBreakMap.breakAll, textAlign && textAlignMap[textAlign], weight && fontWeightStylesMap[weight], asElement === 'em' && emStyles, asElement === 'strong' && strongStyles],
108
96
  style: {
109
97
  WebkitLineClamp: maxLines
@@ -111,10 +99,5 @@ const Text = ({
111
99
  "data-testid": testId,
112
100
  id: id
113
101
  }, children);
114
- return isWrapped ?
115
- // no need to re-apply context if the text is already wrapped
116
- component : jsx(HasTextAncestorContext.Provider, {
117
- value: true
118
- }, component);
119
102
  };
120
103
  export default Text;
@@ -6,4 +6,5 @@ export { default as Flex } from './components/flex';
6
6
  export { default as Grid } from './components/grid';
7
7
  export { default as Bleed } from './components/bleed';
8
8
  export { default as Text } from './components/text';
9
+ export { default as UNSAFE_Pressable } from './components/pressable';
9
10
  export { media, UNSAFE_media, UNSAFE_BREAKPOINTS_CONFIG } from './responsive';
@@ -2,10 +2,13 @@ import _extends from "@babel/runtime/helpers/extends";
2
2
  import _typeof from "@babel/runtime/helpers/typeof";
3
3
  import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
4
4
  import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
5
- var _excluded = ["href", "children", "backgroundColor", "padding", "paddingBlock", "paddingBlockStart", "paddingBlockEnd", "paddingInline", "paddingInlineStart", "paddingInlineEnd", "testId", "xcss", "target", "rel"];
6
- import React, { forwardRef } from 'react';
5
+ var _excluded = ["href", "children", "backgroundColor", "padding", "paddingBlock", "paddingBlockStart", "paddingBlockEnd", "paddingInline", "paddingInlineStart", "paddingInlineEnd", "testId", "xcss", "target", "rel", "onClick", "interactionName", "componentName", "analyticsContext"];
6
+ import React, { forwardRef, useCallback, useContext } from 'react';
7
7
  import invariant from 'tiny-invariant';
8
+ import { usePlatformLeafEventHandler } from '@atlaskit/analytics-next';
8
9
  import { useRouterLink } from '@atlaskit/app-provider';
10
+ import noop from '@atlaskit/ds-lib/noop';
11
+ import InteractionContext from '@atlaskit/interaction-context';
9
12
  import { xcss } from '../xcss/xcss';
10
13
  import Box from './box';
11
14
  // TODO: Duplicated FocusRing styles due to lack of `xcss` support
@@ -44,7 +47,26 @@ var Link = function Link(_ref, ref) {
44
47
  xcssStyles = _ref.xcss,
45
48
  target = _ref.target,
46
49
  rel = _ref.rel,
50
+ _ref$onClick = _ref.onClick,
51
+ providedOnClick = _ref$onClick === void 0 ? noop : _ref$onClick,
52
+ interactionName = _ref.interactionName,
53
+ componentName = _ref.componentName,
54
+ analyticsContext = _ref.analyticsContext,
47
55
  htmlAttributes = _objectWithoutProperties(_ref, _excluded);
56
+ var interactionContext = useContext(InteractionContext);
57
+ var handleClick = useCallback(function (e, analyticsEvent) {
58
+ interactionContext && interactionContext.tracePress(interactionName, e.timeStamp);
59
+ providedOnClick(e, analyticsEvent);
60
+ }, [providedOnClick, interactionContext, interactionName]);
61
+ var onClick = usePlatformLeafEventHandler({
62
+ fn: handleClick,
63
+ action: 'clicked',
64
+ componentName: componentName || 'Anchor',
65
+ packageName: "@atlaskit/primitives",
66
+ packageVersion: "2.1.0",
67
+ analyticsData: analyticsContext,
68
+ actionSubject: 'link'
69
+ });
48
70
  var RouterLink = useRouterLink();
49
71
 
50
72
  // Combine default styles with supplied styles. XCSS does not support deep nested arrays
@@ -81,6 +103,11 @@ var Link = function Link(_ref, ref) {
81
103
  paddingInline: paddingInline,
82
104
  paddingInlineStart: paddingInlineStart,
83
105
  paddingInlineEnd: paddingInlineEnd
106
+ // TODO: This only tracks events if componentName is supplied, which makes tracking opt-in during
107
+ // the transition period. This will be removed once `@atlaskit/button` is bumped to use the latest
108
+ // version of primitives
109
+ ,
110
+ onClick: componentName ? onClick : providedOnClick
84
111
  // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage
85
112
  ,
86
113
  xcss: styles
@@ -93,8 +120,9 @@ var Link = function Link(_ref, ref) {
93
120
  *
94
121
  * @internal Still under development. Do not use.
95
122
  *
96
- * A Link is a primitive component that renders an `<a>` anchor. It utilizes
97
- * the configured router link component in the AppProvider if set.
123
+ * Link is a primitive for building custom anchor links. It's a wrapper around the HTML `<a>` element that provides a consistent API for handling client-side routing and Atlassian Design System styling.
124
+ *
125
+ * This component is mostly used by other design system components, such as the [link component](/components/link/usage).
98
126
  *
99
127
  * - [Examples](https://atlassian.design/components/primitives/link/examples)
100
128
  * - [Code](https://atlassian.design/components/primitives/link/code)
@@ -1,8 +1,11 @@
1
1
  import _extends from "@babel/runtime/helpers/extends";
2
2
  import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
3
3
  import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
4
- var _excluded = ["children", "backgroundColor", "padding", "paddingBlock", "paddingBlockStart", "paddingBlockEnd", "paddingInline", "paddingInlineStart", "paddingInlineEnd", "isDisabled", "type", "testId", "xcss"];
5
- import React, { forwardRef } from 'react';
4
+ var _excluded = ["children", "backgroundColor", "padding", "paddingBlock", "paddingBlockStart", "paddingBlockEnd", "paddingInline", "paddingInlineStart", "paddingInlineEnd", "isDisabled", "type", "testId", "xcss", "onClick", "interactionName", "componentName", "analyticsContext"];
5
+ import React, { forwardRef, useCallback, useContext } from 'react';
6
+ import { usePlatformLeafEventHandler } from '@atlaskit/analytics-next';
7
+ import noop from '@atlaskit/ds-lib/noop';
8
+ import InteractionContext from '@atlaskit/interaction-context';
6
9
  import { xcss } from '../xcss/xcss';
7
10
  import Box from './box';
8
11
  // TODO: Duplicated FocusRing styles due to lack of `xcss` support
@@ -51,7 +54,27 @@ var UNSAFE_PRESSABLE = /*#__PURE__*/forwardRef(function (_ref, ref) {
51
54
  type = _ref$type === void 0 ? 'button' : _ref$type,
52
55
  testId = _ref.testId,
53
56
  xcssStyles = _ref.xcss,
57
+ _ref$onClick = _ref.onClick,
58
+ providedOnClick = _ref$onClick === void 0 ? noop : _ref$onClick,
59
+ interactionName = _ref.interactionName,
60
+ componentName = _ref.componentName,
61
+ analyticsContext = _ref.analyticsContext,
54
62
  htmlAttributes = _objectWithoutProperties(_ref, _excluded);
63
+ var interactionContext = useContext(InteractionContext);
64
+ var handleClick = useCallback(function (e, analyticsEvent) {
65
+ interactionContext && interactionContext.tracePress(interactionName, e.timeStamp);
66
+ providedOnClick(e, analyticsEvent);
67
+ }, [providedOnClick, interactionContext, interactionName]);
68
+ var onClick = usePlatformLeafEventHandler({
69
+ fn: handleClick,
70
+ action: 'clicked',
71
+ componentName: componentName || 'Pressable',
72
+ packageName: "@atlaskit/primitives",
73
+ packageVersion: "2.1.0",
74
+ analyticsData: analyticsContext,
75
+ actionSubject: 'button'
76
+ });
77
+
55
78
  // Combine default styles with supplied styles. XCSS does not support deep nested arrays
56
79
  var styles = [xcss({
57
80
  cursor: isDisabled ? 'not-allowed' : 'pointer'
@@ -61,7 +84,12 @@ var UNSAFE_PRESSABLE = /*#__PURE__*/forwardRef(function (_ref, ref) {
61
84
  as: "button",
62
85
  ref: ref,
63
86
  testId: testId,
64
- type: type,
87
+ type: type
88
+ // TODO: This only tracks events if componentName is supplied, which makes tracking opt-in during
89
+ // the transition period. This will be removed once `@atlaskit/button` is bumped to use the latest
90
+ // version of primitives
91
+ ,
92
+ onClick: componentName ? onClick : providedOnClick,
65
93
  backgroundColor: backgroundColor,
66
94
  padding: padding,
67
95
  paddingBlock: paddingBlock,
@@ -4,7 +4,7 @@ var _excluded = ["children"];
4
4
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
5
5
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
6
6
  /** @jsx jsx */
7
- import { createContext, Fragment, useContext } from 'react';
7
+
8
8
  import { css, jsx } from '@emotion/react';
9
9
  import invariant from 'tiny-invariant';
10
10
  import { bodyTextStylesMap, fontWeightStylesMap, inverseColorMap, textColorStylesMap, uiTextStylesMap } from '../xcss/style-maps.partial';
@@ -50,19 +50,14 @@ var wordBreakMap = {
50
50
  */
51
51
  var useColor = function useColor(colorProp) {
52
52
  var surface = useSurface();
53
- var inverseTextColor = inverseColorMap[surface];
54
53
 
55
54
  /**
56
55
  * Where the color of the surface is inverted we override the user choice
57
56
  * as there is no valid choice that is not covered by the override.
58
57
  */
59
- var color = inverseTextColor !== null && inverseTextColor !== void 0 ? inverseTextColor : colorProp;
58
+ var color = inverseColorMap.hasOwnProperty(surface) ? inverseColorMap[surface] : colorProp;
60
59
  return color;
61
60
  };
62
- var HasTextAncestorContext = /*#__PURE__*/createContext(false);
63
- var useHasTextAncestor = function useHasTextAncestor() {
64
- return useContext(HasTextAncestorContext);
65
- };
66
61
 
67
62
  /**
68
63
  * __Text__
@@ -77,8 +72,7 @@ var Text = function Text(_ref) {
77
72
  var children = _ref.children,
78
73
  props = _objectWithoutProperties(_ref, _excluded);
79
74
  var asElement = props.as,
80
- _props$color = props.color,
81
- colorProp = _props$color === void 0 ? 'color.text' : _props$color,
75
+ colorProp = props.color,
82
76
  textAlign = props.textAlign,
83
77
  testId = props.testId,
84
78
  id = props.id,
@@ -97,16 +91,7 @@ var Text = function Text(_ref) {
97
91
  maxLines = props.maxLines;
98
92
  }
99
93
  var color = useColor(colorProp);
100
- var isWrapped = useHasTextAncestor();
101
-
102
- /**
103
- * If the text is already wrapped and applies no props we can just
104
- * render the children directly as a fragment.
105
- */
106
- if (isWrapped && Object.keys(props).length === 0) {
107
- return jsx(Fragment, null, children);
108
- }
109
- var component = jsx(Component, {
94
+ return jsx(Component, {
110
95
  css: [resetStyles, variant && variantStyles[variant], color && textColorStylesMap[color], maxLines && truncationStyles, maxLines === 1 && wordBreakMap.breakAll, textAlign && textAlignMap[textAlign], weight && fontWeightStylesMap[weight], asElement === 'em' && emStyles, asElement === 'strong' && strongStyles],
111
96
  style: {
112
97
  WebkitLineClamp: maxLines
@@ -114,10 +99,5 @@ var Text = function Text(_ref) {
114
99
  "data-testid": testId,
115
100
  id: id
116
101
  }, children);
117
- return isWrapped ?
118
- // no need to re-apply context if the text is already wrapped
119
- component : jsx(HasTextAncestorContext.Provider, {
120
- value: true
121
- }, component);
122
102
  };
123
103
  export default Text;
package/dist/esm/index.js CHANGED
@@ -6,4 +6,5 @@ export { default as Flex } from './components/flex';
6
6
  export { default as Grid } from './components/grid';
7
7
  export { default as Bleed } from './components/bleed';
8
8
  export { default as Text } from './components/text';
9
+ export { default as UNSAFE_Pressable } from './components/pressable';
9
10
  export { media, UNSAFE_media, UNSAFE_BREAKPOINTS_CONFIG } from './responsive';
@@ -1,30 +1,68 @@
1
1
  import React, { type ReactNode, type Ref } from 'react';
2
+ import { UIAnalyticsEvent } from '@atlaskit/analytics-next';
2
3
  import { type RouterLinkComponentProps } from '@atlaskit/app-provider';
3
4
  import { type BoxProps } from './box';
4
- export type LinkProps<RouterLinkConfig extends Record<string, any> = never> = RouterLinkComponentProps<RouterLinkConfig> & Omit<BoxProps<'a'>, 'href' | 'as' | 'children' | 'style'> & {
5
+ export type LinkProps<RouterLinkConfig extends Record<string, any> = never> = RouterLinkComponentProps<RouterLinkConfig> & Omit<BoxProps<'a'>, 'href' | 'as' | 'children' | 'style' | 'onClick'> & {
5
6
  /**
6
7
  * `children` should be defined to ensure links have text.
7
8
  */
8
9
  children: ReactNode;
10
+ /**
11
+ * Handler to be called on click. The second argument can be used to track analytics data. See the tutorial in the analytics-next package for details.
12
+ */
13
+ onClick?: (e: React.MouseEvent<HTMLAnchorElement>, analyticsEvent?: UIAnalyticsEvent) => void;
14
+ /**
15
+ * An optional name used to identify the interaction type to press listeners. For example, interaction tracing. For more information,
16
+ * see [UFO integration into Design System components](https://go.atlassian.com/react-ufo-dst-integration).
17
+ */
18
+ interactionName?: string;
19
+ /**
20
+ * An optional component name used to identify this component to press listeners. This can be used if a parent component's name is preferred. For example, interaction tracing. For more information,
21
+ * see [UFO integration into Design System components](https://go.atlassian.com/react-ufo-dst-integration).
22
+ */
23
+ componentName?: string;
24
+ /**
25
+ * Additional information to be included in the `context` of analytics events that come from anchor.
26
+ */
27
+ analyticsContext?: Record<string, any>;
9
28
  };
10
- declare const Link: <RouterLinkConfig extends Record<string, any> = never>({ href, children, backgroundColor, padding, paddingBlock, paddingBlockStart, paddingBlockEnd, paddingInline, paddingInlineStart, paddingInlineEnd, testId, xcss: xcssStyles, target, rel, ...htmlAttributes }: LinkProps<RouterLinkConfig>, ref: Ref<HTMLAnchorElement>) => JSX.Element;
29
+ declare const Link: <RouterLinkConfig extends Record<string, any> = never>({ href, children, backgroundColor, padding, paddingBlock, paddingBlockStart, paddingBlockEnd, paddingInline, paddingInlineStart, paddingInlineEnd, testId, xcss: xcssStyles, target, rel, onClick: providedOnClick, interactionName, componentName, analyticsContext, ...htmlAttributes }: LinkProps<RouterLinkConfig>, ref: Ref<HTMLAnchorElement>) => JSX.Element;
11
30
  /**
12
31
  * __UNSAFE_LINK__
13
32
  *
14
33
  * @internal Still under development. Do not use.
15
34
  *
16
- * A Link is a primitive component that renders an `<a>` anchor. It utilizes
17
- * the configured router link component in the AppProvider if set.
35
+ * Link is a primitive for building custom anchor links. It's a wrapper around the HTML `<a>` element that provides a consistent API for handling client-side routing and Atlassian Design System styling.
36
+ *
37
+ * This component is mostly used by other design system components, such as the [link component](/components/link/usage).
18
38
  *
19
39
  * - [Examples](https://atlassian.design/components/primitives/link/examples)
20
40
  * - [Code](https://atlassian.design/components/primitives/link/code)
21
41
  * - [Usage](https://atlassian.design/components/primitives/link/usage)
22
42
  */
23
- declare const UNSAFE_LINK: <RouterLinkConfig extends Record<string, any> = never>(props: RouterLinkComponentProps<RouterLinkConfig> & Omit<BoxProps<"a">, "style" | "children" | "as" | "href"> & {
43
+ declare const UNSAFE_LINK: <RouterLinkConfig extends Record<string, any> = never>(props: RouterLinkComponentProps<RouterLinkConfig> & Omit<BoxProps<"a">, "style" | "children" | "as" | "onClick" | "href"> & {
24
44
  /**
25
45
  * `children` should be defined to ensure links have text.
26
46
  */
27
47
  children: ReactNode;
48
+ /**
49
+ * Handler to be called on click. The second argument can be used to track analytics data. See the tutorial in the analytics-next package for details.
50
+ */
51
+ onClick?: ((e: React.MouseEvent<HTMLAnchorElement>, analyticsEvent?: UIAnalyticsEvent) => void) | undefined;
52
+ /**
53
+ * An optional name used to identify the interaction type to press listeners. For example, interaction tracing. For more information,
54
+ * see [UFO integration into Design System components](https://go.atlassian.com/react-ufo-dst-integration).
55
+ */
56
+ interactionName?: string | undefined;
57
+ /**
58
+ * An optional component name used to identify this component to press listeners. This can be used if a parent component's name is preferred. For example, interaction tracing. For more information,
59
+ * see [UFO integration into Design System components](https://go.atlassian.com/react-ufo-dst-integration).
60
+ */
61
+ componentName?: string | undefined;
62
+ /**
63
+ * Additional information to be included in the `context` of analytics events that come from anchor.
64
+ */
65
+ analyticsContext?: Record<string, any> | undefined;
28
66
  } & {
29
67
  ref?: React.Ref<HTMLAnchorElement> | undefined;
30
68
  }) => ReturnType<typeof Link>;
@@ -1,14 +1,32 @@
1
- import { type ReactElement, type ReactNode } from 'react';
1
+ import React, { type ReactNode } from 'react';
2
+ import { UIAnalyticsEvent } from '@atlaskit/analytics-next';
2
3
  import { type BoxProps } from './box';
3
- export type PressableProps = Omit<BoxProps<'button'>, 'disabled' | 'as' | 'children' | 'role' | 'style'> & {
4
+ export type PressableProps = Omit<BoxProps<'button'>, 'disabled' | 'as' | 'children' | 'role' | 'style' | 'onClick'> & {
4
5
  /**
5
6
  * `children` should be defined to ensure buttons are not empty,
6
7
  * because they should have labels.
7
8
  */
8
9
  children: ReactNode;
9
10
  isDisabled?: boolean;
11
+ /**
12
+ * Handler to be called on click. The second argument can be used to track analytics data. See the tutorial in the analytics-next package for details.
13
+ */
14
+ onClick?: (e: React.MouseEvent<HTMLButtonElement>, analyticsEvent?: UIAnalyticsEvent) => void;
15
+ /**
16
+ * An optional name used to identify the interaction type to press listeners. For example, interaction tracing. For more information,
17
+ * see [UFO integration into Design System components](https://go.atlassian.com/react-ufo-dst-integration).
18
+ */
19
+ interactionName?: string;
20
+ /**
21
+ * An optional component name used to identify this component to press listeners. This can be used if a parent component's name is preferred. For example, interaction tracing. For more information,
22
+ * see [UFO integration into Design System components](https://go.atlassian.com/react-ufo-dst-integration).
23
+ */
24
+ componentName?: string;
25
+ /**
26
+ * Additional information to be included in the `context` of analytics events that come from pressable.
27
+ */
28
+ analyticsContext?: Record<string, any>;
10
29
  };
11
- type PressableComponent = (props: PressableProps, displayName: string) => ReactElement | null;
12
30
  /**
13
31
  * __UNSAFE_PRESSABLE__
14
32
  *
@@ -20,5 +38,30 @@ type PressableComponent = (props: PressableProps, displayName: string) => ReactE
20
38
  * - [Code](https://atlassian.design/components/primitives/pressable/code)
21
39
  * - [Usage](https://atlassian.design/components/primitives/pressable/usage)
22
40
  */
23
- declare const UNSAFE_PRESSABLE: PressableComponent;
41
+ declare const UNSAFE_PRESSABLE: React.ForwardRefExoticComponent<Pick<Omit<BoxProps<"button">, "style" | "disabled" | "children" | "as" | "role" | "onClick"> & {
42
+ /**
43
+ * `children` should be defined to ensure buttons are not empty,
44
+ * because they should have labels.
45
+ */
46
+ children: ReactNode;
47
+ isDisabled?: boolean | undefined;
48
+ /**
49
+ * Handler to be called on click. The second argument can be used to track analytics data. See the tutorial in the analytics-next package for details.
50
+ */
51
+ onClick?: ((e: React.MouseEvent<HTMLButtonElement>, analyticsEvent?: UIAnalyticsEvent) => void) | undefined;
52
+ /**
53
+ * An optional name used to identify the interaction type to press listeners. For example, interaction tracing. For more information,
54
+ * see [UFO integration into Design System components](https://go.atlassian.com/react-ufo-dst-integration).
55
+ */
56
+ interactionName?: string | undefined;
57
+ /**
58
+ * An optional component name used to identify this component to press listeners. This can be used if a parent component's name is preferred. For example, interaction tracing. For more information,
59
+ * see [UFO integration into Design System components](https://go.atlassian.com/react-ufo-dst-integration).
60
+ */
61
+ componentName?: string | undefined;
62
+ /**
63
+ * Additional information to be included in the `context` of analytics events that come from pressable.
64
+ */
65
+ analyticsContext?: Record<string, any> | undefined;
66
+ }, "padding" | "paddingBlock" | "paddingBlockStart" | "paddingBlockEnd" | "paddingInline" | "paddingInlineStart" | "paddingInlineEnd" | "backgroundColor" | "color" | "translate" | "key" | "value" | "hidden" | "children" | "form" | "slot" | "title" | "name" | "type" | "defaultChecked" | "defaultValue" | "suppressContentEditableWarning" | "suppressHydrationWarning" | "accessKey" | "contentEditable" | "contextMenu" | "dir" | "draggable" | "id" | "lang" | "placeholder" | "spellCheck" | "tabIndex" | "radioGroup" | "about" | "datatype" | "inlist" | "prefix" | "property" | "resource" | "typeof" | "vocab" | "autoCapitalize" | "autoCorrect" | "autoSave" | "itemProp" | "itemScope" | "itemType" | "itemID" | "itemRef" | "results" | "security" | "unselectable" | "inputMode" | "is" | "aria-activedescendant" | "aria-atomic" | "aria-autocomplete" | "aria-busy" | "aria-checked" | "aria-colcount" | "aria-colindex" | "aria-colspan" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-expanded" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-hidden" | "aria-invalid" | "aria-keyshortcuts" | "aria-label" | "aria-labelledby" | "aria-level" | "aria-live" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-orientation" | "aria-owns" | "aria-placeholder" | "aria-posinset" | "aria-pressed" | "aria-readonly" | "aria-relevant" | "aria-required" | "aria-roledescription" | "aria-rowcount" | "aria-rowindex" | "aria-rowspan" | "aria-selected" | "aria-setsize" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "dangerouslySetInnerHTML" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChange" | "onChangeCapture" | "onBeforeInput" | "onBeforeInputCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onError" | "onErrorCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onAbort" | "onAbortCapture" | "onCanPlay" | "onCanPlayCapture" | "onCanPlayThrough" | "onCanPlayThroughCapture" | "onDurationChange" | "onDurationChangeCapture" | "onEmptied" | "onEmptiedCapture" | "onEncrypted" | "onEncryptedCapture" | "onEnded" | "onEndedCapture" | "onLoadedData" | "onLoadedDataCapture" | "onLoadedMetadata" | "onLoadedMetadataCapture" | "onLoadStart" | "onLoadStartCapture" | "onPause" | "onPauseCapture" | "onPlay" | "onPlayCapture" | "onPlaying" | "onPlayingCapture" | "onProgress" | "onProgressCapture" | "onRateChange" | "onRateChangeCapture" | "onSeeked" | "onSeekedCapture" | "onSeeking" | "onSeekingCapture" | "onStalled" | "onStalledCapture" | "onSuspend" | "onSuspendCapture" | "onTimeUpdate" | "onTimeUpdateCapture" | "onVolumeChange" | "onVolumeChangeCapture" | "onWaiting" | "onWaitingCapture" | "onAuxClick" | "onAuxClickCapture" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDoubleClick" | "onDoubleClickCapture" | "onDrag" | "onDragCapture" | "onDragEnd" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStart" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onSelect" | "onSelectCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerEnterCapture" | "onPointerLeave" | "onPointerLeaveCapture" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onWheel" | "onWheelCapture" | "onAnimationStart" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onTransitionEnd" | "onTransitionEndCapture" | "autoFocus" | "formAction" | "formEncType" | "formMethod" | "formNoValidate" | "formTarget" | "testId" | "xcss" | "data-testid" | "isDisabled" | "interactionName" | "componentName" | "analyticsContext"> & React.RefAttributes<HTMLButtonElement>>;
24
67
  export default UNSAFE_PRESSABLE;
@@ -15,5 +15,7 @@ export { default as Bleed } from './components/bleed';
15
15
  export type { BleedProps } from './components/bleed';
16
16
  export { default as Text } from './components/text';
17
17
  export type { TextProps } from './components/text';
18
+ export { default as UNSAFE_Pressable } from './components/pressable';
19
+ export type { PressableProps as UNSAFE_PressableProps } from './components/pressable';
18
20
  export { media, UNSAFE_media, UNSAFE_BREAKPOINTS_CONFIG } from './responsive';
19
21
  export type { Breakpoint, MediaQuery } from './responsive';
@@ -1,30 +1,68 @@
1
1
  import React, { type ReactNode, type Ref } from 'react';
2
+ import { UIAnalyticsEvent } from '@atlaskit/analytics-next';
2
3
  import { type RouterLinkComponentProps } from '@atlaskit/app-provider';
3
4
  import { type BoxProps } from './box';
4
- export type LinkProps<RouterLinkConfig extends Record<string, any> = never> = RouterLinkComponentProps<RouterLinkConfig> & Omit<BoxProps<'a'>, 'href' | 'as' | 'children' | 'style'> & {
5
+ export type LinkProps<RouterLinkConfig extends Record<string, any> = never> = RouterLinkComponentProps<RouterLinkConfig> & Omit<BoxProps<'a'>, 'href' | 'as' | 'children' | 'style' | 'onClick'> & {
5
6
  /**
6
7
  * `children` should be defined to ensure links have text.
7
8
  */
8
9
  children: ReactNode;
10
+ /**
11
+ * Handler to be called on click. The second argument can be used to track analytics data. See the tutorial in the analytics-next package for details.
12
+ */
13
+ onClick?: (e: React.MouseEvent<HTMLAnchorElement>, analyticsEvent?: UIAnalyticsEvent) => void;
14
+ /**
15
+ * An optional name used to identify the interaction type to press listeners. For example, interaction tracing. For more information,
16
+ * see [UFO integration into Design System components](https://go.atlassian.com/react-ufo-dst-integration).
17
+ */
18
+ interactionName?: string;
19
+ /**
20
+ * An optional component name used to identify this component to press listeners. This can be used if a parent component's name is preferred. For example, interaction tracing. For more information,
21
+ * see [UFO integration into Design System components](https://go.atlassian.com/react-ufo-dst-integration).
22
+ */
23
+ componentName?: string;
24
+ /**
25
+ * Additional information to be included in the `context` of analytics events that come from anchor.
26
+ */
27
+ analyticsContext?: Record<string, any>;
9
28
  };
10
- declare const Link: <RouterLinkConfig extends Record<string, any> = never>({ href, children, backgroundColor, padding, paddingBlock, paddingBlockStart, paddingBlockEnd, paddingInline, paddingInlineStart, paddingInlineEnd, testId, xcss: xcssStyles, target, rel, ...htmlAttributes }: LinkProps<RouterLinkConfig>, ref: Ref<HTMLAnchorElement>) => JSX.Element;
29
+ declare const Link: <RouterLinkConfig extends Record<string, any> = never>({ href, children, backgroundColor, padding, paddingBlock, paddingBlockStart, paddingBlockEnd, paddingInline, paddingInlineStart, paddingInlineEnd, testId, xcss: xcssStyles, target, rel, onClick: providedOnClick, interactionName, componentName, analyticsContext, ...htmlAttributes }: LinkProps<RouterLinkConfig>, ref: Ref<HTMLAnchorElement>) => JSX.Element;
11
30
  /**
12
31
  * __UNSAFE_LINK__
13
32
  *
14
33
  * @internal Still under development. Do not use.
15
34
  *
16
- * A Link is a primitive component that renders an `<a>` anchor. It utilizes
17
- * the configured router link component in the AppProvider if set.
35
+ * Link is a primitive for building custom anchor links. It's a wrapper around the HTML `<a>` element that provides a consistent API for handling client-side routing and Atlassian Design System styling.
36
+ *
37
+ * This component is mostly used by other design system components, such as the [link component](/components/link/usage).
18
38
  *
19
39
  * - [Examples](https://atlassian.design/components/primitives/link/examples)
20
40
  * - [Code](https://atlassian.design/components/primitives/link/code)
21
41
  * - [Usage](https://atlassian.design/components/primitives/link/usage)
22
42
  */
23
- declare const UNSAFE_LINK: <RouterLinkConfig extends Record<string, any> = never>(props: RouterLinkComponentProps<RouterLinkConfig> & Omit<BoxProps<"a">, "style" | "children" | "as" | "href"> & {
43
+ declare const UNSAFE_LINK: <RouterLinkConfig extends Record<string, any> = never>(props: RouterLinkComponentProps<RouterLinkConfig> & Omit<BoxProps<"a">, "style" | "children" | "as" | "onClick" | "href"> & {
24
44
  /**
25
45
  * `children` should be defined to ensure links have text.
26
46
  */
27
47
  children: ReactNode;
48
+ /**
49
+ * Handler to be called on click. The second argument can be used to track analytics data. See the tutorial in the analytics-next package for details.
50
+ */
51
+ onClick?: ((e: React.MouseEvent<HTMLAnchorElement>, analyticsEvent?: UIAnalyticsEvent) => void) | undefined;
52
+ /**
53
+ * An optional name used to identify the interaction type to press listeners. For example, interaction tracing. For more information,
54
+ * see [UFO integration into Design System components](https://go.atlassian.com/react-ufo-dst-integration).
55
+ */
56
+ interactionName?: string | undefined;
57
+ /**
58
+ * An optional component name used to identify this component to press listeners. This can be used if a parent component's name is preferred. For example, interaction tracing. For more information,
59
+ * see [UFO integration into Design System components](https://go.atlassian.com/react-ufo-dst-integration).
60
+ */
61
+ componentName?: string | undefined;
62
+ /**
63
+ * Additional information to be included in the `context` of analytics events that come from anchor.
64
+ */
65
+ analyticsContext?: Record<string, any> | undefined;
28
66
  } & {
29
67
  ref?: React.Ref<HTMLAnchorElement> | undefined;
30
68
  }) => ReturnType<typeof Link>;
@@ -1,14 +1,32 @@
1
- import { type ReactElement, type ReactNode } from 'react';
1
+ import React, { type ReactNode } from 'react';
2
+ import { UIAnalyticsEvent } from '@atlaskit/analytics-next';
2
3
  import { type BoxProps } from './box';
3
- export type PressableProps = Omit<BoxProps<'button'>, 'disabled' | 'as' | 'children' | 'role' | 'style'> & {
4
+ export type PressableProps = Omit<BoxProps<'button'>, 'disabled' | 'as' | 'children' | 'role' | 'style' | 'onClick'> & {
4
5
  /**
5
6
  * `children` should be defined to ensure buttons are not empty,
6
7
  * because they should have labels.
7
8
  */
8
9
  children: ReactNode;
9
10
  isDisabled?: boolean;
11
+ /**
12
+ * Handler to be called on click. The second argument can be used to track analytics data. See the tutorial in the analytics-next package for details.
13
+ */
14
+ onClick?: (e: React.MouseEvent<HTMLButtonElement>, analyticsEvent?: UIAnalyticsEvent) => void;
15
+ /**
16
+ * An optional name used to identify the interaction type to press listeners. For example, interaction tracing. For more information,
17
+ * see [UFO integration into Design System components](https://go.atlassian.com/react-ufo-dst-integration).
18
+ */
19
+ interactionName?: string;
20
+ /**
21
+ * An optional component name used to identify this component to press listeners. This can be used if a parent component's name is preferred. For example, interaction tracing. For more information,
22
+ * see [UFO integration into Design System components](https://go.atlassian.com/react-ufo-dst-integration).
23
+ */
24
+ componentName?: string;
25
+ /**
26
+ * Additional information to be included in the `context` of analytics events that come from pressable.
27
+ */
28
+ analyticsContext?: Record<string, any>;
10
29
  };
11
- type PressableComponent = (props: PressableProps, displayName: string) => ReactElement | null;
12
30
  /**
13
31
  * __UNSAFE_PRESSABLE__
14
32
  *
@@ -20,5 +38,30 @@ type PressableComponent = (props: PressableProps, displayName: string) => ReactE
20
38
  * - [Code](https://atlassian.design/components/primitives/pressable/code)
21
39
  * - [Usage](https://atlassian.design/components/primitives/pressable/usage)
22
40
  */
23
- declare const UNSAFE_PRESSABLE: PressableComponent;
41
+ declare const UNSAFE_PRESSABLE: React.ForwardRefExoticComponent<Pick<Omit<BoxProps<"button">, "style" | "disabled" | "children" | "as" | "role" | "onClick"> & {
42
+ /**
43
+ * `children` should be defined to ensure buttons are not empty,
44
+ * because they should have labels.
45
+ */
46
+ children: ReactNode;
47
+ isDisabled?: boolean | undefined;
48
+ /**
49
+ * Handler to be called on click. The second argument can be used to track analytics data. See the tutorial in the analytics-next package for details.
50
+ */
51
+ onClick?: ((e: React.MouseEvent<HTMLButtonElement>, analyticsEvent?: UIAnalyticsEvent) => void) | undefined;
52
+ /**
53
+ * An optional name used to identify the interaction type to press listeners. For example, interaction tracing. For more information,
54
+ * see [UFO integration into Design System components](https://go.atlassian.com/react-ufo-dst-integration).
55
+ */
56
+ interactionName?: string | undefined;
57
+ /**
58
+ * An optional component name used to identify this component to press listeners. This can be used if a parent component's name is preferred. For example, interaction tracing. For more information,
59
+ * see [UFO integration into Design System components](https://go.atlassian.com/react-ufo-dst-integration).
60
+ */
61
+ componentName?: string | undefined;
62
+ /**
63
+ * Additional information to be included in the `context` of analytics events that come from pressable.
64
+ */
65
+ analyticsContext?: Record<string, any> | undefined;
66
+ }, "padding" | "paddingBlock" | "paddingBlockStart" | "paddingBlockEnd" | "paddingInline" | "paddingInlineStart" | "paddingInlineEnd" | "backgroundColor" | "color" | "translate" | "key" | "value" | "hidden" | "children" | "form" | "slot" | "title" | "name" | "type" | "defaultChecked" | "defaultValue" | "suppressContentEditableWarning" | "suppressHydrationWarning" | "accessKey" | "contentEditable" | "contextMenu" | "dir" | "draggable" | "id" | "lang" | "placeholder" | "spellCheck" | "tabIndex" | "radioGroup" | "about" | "datatype" | "inlist" | "prefix" | "property" | "resource" | "typeof" | "vocab" | "autoCapitalize" | "autoCorrect" | "autoSave" | "itemProp" | "itemScope" | "itemType" | "itemID" | "itemRef" | "results" | "security" | "unselectable" | "inputMode" | "is" | "aria-activedescendant" | "aria-atomic" | "aria-autocomplete" | "aria-busy" | "aria-checked" | "aria-colcount" | "aria-colindex" | "aria-colspan" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-expanded" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-hidden" | "aria-invalid" | "aria-keyshortcuts" | "aria-label" | "aria-labelledby" | "aria-level" | "aria-live" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-orientation" | "aria-owns" | "aria-placeholder" | "aria-posinset" | "aria-pressed" | "aria-readonly" | "aria-relevant" | "aria-required" | "aria-roledescription" | "aria-rowcount" | "aria-rowindex" | "aria-rowspan" | "aria-selected" | "aria-setsize" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "dangerouslySetInnerHTML" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChange" | "onChangeCapture" | "onBeforeInput" | "onBeforeInputCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onError" | "onErrorCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onAbort" | "onAbortCapture" | "onCanPlay" | "onCanPlayCapture" | "onCanPlayThrough" | "onCanPlayThroughCapture" | "onDurationChange" | "onDurationChangeCapture" | "onEmptied" | "onEmptiedCapture" | "onEncrypted" | "onEncryptedCapture" | "onEnded" | "onEndedCapture" | "onLoadedData" | "onLoadedDataCapture" | "onLoadedMetadata" | "onLoadedMetadataCapture" | "onLoadStart" | "onLoadStartCapture" | "onPause" | "onPauseCapture" | "onPlay" | "onPlayCapture" | "onPlaying" | "onPlayingCapture" | "onProgress" | "onProgressCapture" | "onRateChange" | "onRateChangeCapture" | "onSeeked" | "onSeekedCapture" | "onSeeking" | "onSeekingCapture" | "onStalled" | "onStalledCapture" | "onSuspend" | "onSuspendCapture" | "onTimeUpdate" | "onTimeUpdateCapture" | "onVolumeChange" | "onVolumeChangeCapture" | "onWaiting" | "onWaitingCapture" | "onAuxClick" | "onAuxClickCapture" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDoubleClick" | "onDoubleClickCapture" | "onDrag" | "onDragCapture" | "onDragEnd" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStart" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onSelect" | "onSelectCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerEnterCapture" | "onPointerLeave" | "onPointerLeaveCapture" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onWheel" | "onWheelCapture" | "onAnimationStart" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onTransitionEnd" | "onTransitionEndCapture" | "autoFocus" | "formAction" | "formEncType" | "formMethod" | "formNoValidate" | "formTarget" | "testId" | "xcss" | "data-testid" | "isDisabled" | "interactionName" | "componentName" | "analyticsContext"> & React.RefAttributes<HTMLButtonElement>>;
24
67
  export default UNSAFE_PRESSABLE;
@@ -15,5 +15,7 @@ export { default as Bleed } from './components/bleed';
15
15
  export type { BleedProps } from './components/bleed';
16
16
  export { default as Text } from './components/text';
17
17
  export type { TextProps } from './components/text';
18
+ export { default as UNSAFE_Pressable } from './components/pressable';
19
+ export type { PressableProps as UNSAFE_PressableProps } from './components/pressable';
18
20
  export { media, UNSAFE_media, UNSAFE_BREAKPOINTS_CONFIG } from './responsive';
19
21
  export type { Breakpoint, MediaQuery } from './responsive';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/primitives",
3
- "version": "2.0.3",
3
+ "version": "2.1.0",
4
4
  "description": "Primitives are token-backed low-level building blocks.",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/"
@@ -104,7 +104,10 @@
104
104
  "codegen-styles": "ts-node -r tsconfig-paths/register ./scripts/codegen-styles.tsx"
105
105
  },
106
106
  "dependencies": {
107
+ "@atlaskit/analytics-next": "^9.2.0",
107
108
  "@atlaskit/app-provider": "^1.0.0",
109
+ "@atlaskit/ds-lib": "^2.2.0",
110
+ "@atlaskit/interaction-context": "^2.1.0",
108
111
  "@atlaskit/tokens": "^1.38.0",
109
112
  "@babel/runtime": "^7.0.0",
110
113
  "@emotion/react": "^11.7.1",
@@ -117,7 +120,6 @@
117
120
  },
118
121
  "devDependencies": {
119
122
  "@af/accessibility-testing": "*",
120
- "@atlaskit/ds-lib": "*",
121
123
  "@atlaskit/ssr": "*",
122
124
  "@atlaskit/visual-regression": "*",
123
125
  "@atlassian/atlassian-frontend-prettier-config-1.0.1": "npm:@atlassian/atlassian-frontend-prettier-config@1.0.1",