@coreui/react-pro 5.0.0 → 5.1.0-alpha.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/README.md +1 -1
- package/dist/cjs/components/index.d.ts +1 -0
- package/dist/cjs/components/popover/CPopover.js +41 -40
- package/dist/cjs/components/popover/CPopover.js.map +1 -1
- package/dist/cjs/components/rating/CRating.d.ts +70 -0
- package/dist/cjs/components/rating/CRating.js +123 -0
- package/dist/cjs/components/rating/CRating.js.map +1 -0
- package/dist/cjs/components/rating/index.d.ts +2 -0
- package/dist/cjs/components/tooltip/CTooltip.js +44 -40
- package/dist/cjs/components/tooltip/CTooltip.js.map +1 -1
- package/dist/cjs/hooks/usePopper.d.ts +1 -0
- package/dist/cjs/hooks/usePopper.js +11 -4
- package/dist/cjs/hooks/usePopper.js.map +1 -1
- package/dist/cjs/hooks/useStateWithCallback.d.ts +1 -1
- package/dist/cjs/index.js +2 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/node_modules/classnames/index.js +45 -27
- package/dist/cjs/node_modules/classnames/index.js.map +1 -1
- package/dist/esm/components/index.d.ts +1 -0
- package/dist/esm/components/popover/CPopover.js +41 -40
- package/dist/esm/components/popover/CPopover.js.map +1 -1
- package/dist/esm/components/rating/CRating.d.ts +70 -0
- package/dist/esm/components/rating/CRating.js +121 -0
- package/dist/esm/components/rating/CRating.js.map +1 -0
- package/dist/esm/components/rating/index.d.ts +2 -0
- package/dist/esm/components/tooltip/CTooltip.js +44 -40
- package/dist/esm/components/tooltip/CTooltip.js.map +1 -1
- package/dist/esm/hooks/usePopper.d.ts +1 -0
- package/dist/esm/hooks/usePopper.js +11 -4
- package/dist/esm/hooks/usePopper.js.map +1 -1
- package/dist/esm/hooks/useStateWithCallback.d.ts +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/node_modules/classnames/index.js +45 -27
- package/dist/esm/node_modules/classnames/index.js.map +1 -1
- package/package.json +2 -2
- package/src/components/index.ts +1 -0
- package/src/components/popover/CPopover.tsx +51 -66
- package/src/components/rating/CRating.tsx +291 -0
- package/src/components/rating/index.ts +3 -0
- package/src/components/tooltip/CTooltip.tsx +55 -66
- package/src/hooks/usePopper.ts +15 -5
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { useRef } from 'react';
|
|
2
2
|
import { createPopper } from '@popperjs/core';
|
|
3
|
-
import executeAfterTransition from '../utils/executeAfterTransition.js';
|
|
4
3
|
|
|
5
4
|
var usePopper = function () {
|
|
6
5
|
var _popper = useRef();
|
|
@@ -12,16 +11,24 @@ var usePopper = function () {
|
|
|
12
11
|
var destroyPopper = function () {
|
|
13
12
|
var popperInstance = _popper.current;
|
|
14
13
|
if (popperInstance && el.current) {
|
|
15
|
-
|
|
16
|
-
popperInstance.destroy();
|
|
17
|
-
}, el.current);
|
|
14
|
+
popperInstance.destroy();
|
|
18
15
|
}
|
|
19
16
|
_popper.current = undefined;
|
|
20
17
|
};
|
|
18
|
+
var updatePopper = function (options) {
|
|
19
|
+
var popperInstance = _popper.current;
|
|
20
|
+
if (popperInstance && options) {
|
|
21
|
+
popperInstance.setOptions(options);
|
|
22
|
+
}
|
|
23
|
+
if (popperInstance) {
|
|
24
|
+
popperInstance.update();
|
|
25
|
+
}
|
|
26
|
+
};
|
|
21
27
|
return {
|
|
22
28
|
popper: _popper.current,
|
|
23
29
|
initPopper: initPopper,
|
|
24
30
|
destroyPopper: destroyPopper,
|
|
31
|
+
updatePopper: updatePopper,
|
|
25
32
|
};
|
|
26
33
|
};
|
|
27
34
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePopper.js","sources":["../../../src/hooks/usePopper.ts"],"sourcesContent":[null],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"usePopper.js","sources":["../../../src/hooks/usePopper.ts"],"sourcesContent":[null],"names":[],"mappings":";;;AAWa,IAAA,SAAS,GAAG,YAAA;AACvB,IAAA,IAAM,OAAO,GAAG,MAAM,EAAY,CAAA;AAClC,IAAA,IAAM,EAAE,GAAG,MAAM,EAAe,CAAA;AAEhC,IAAA,IAAM,UAAU,GAAG,UAAC,SAAsB,EAAE,MAAmB,EAAE,OAAyB,EAAA;QACxF,OAAO,CAAC,OAAO,GAAG,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,CAAA;AAC1D,QAAA,EAAE,CAAC,OAAO,GAAG,MAAM,CAAA;AACrB,KAAC,CAAA;AAED,IAAA,IAAM,aAAa,GAAG,YAAA;AACpB,QAAA,IAAM,cAAc,GAAG,OAAO,CAAC,OAAO,CAAA;AAEtC,QAAA,IAAI,cAAc,IAAI,EAAE,CAAC,OAAO,EAAE;YAChC,cAAc,CAAC,OAAO,EAAE,CAAA;SACzB;AAED,QAAA,OAAO,CAAC,OAAO,GAAG,SAAS,CAAA;AAC7B,KAAC,CAAA;IAED,IAAM,YAAY,GAAG,UAAC,OAA0B,EAAA;AAC9C,QAAA,IAAM,cAAc,GAAG,OAAO,CAAC,OAAO,CAAA;AAEtC,QAAA,IAAI,cAAc,IAAI,OAAO,EAAE;AAC7B,YAAA,cAAc,CAAC,UAAU,CAAC,OAAO,CAAC,CAAA;SACnC;QAED,IAAI,cAAc,EAAE;YAClB,cAAc,CAAC,MAAM,EAAE,CAAA;SACxB;AACH,KAAC,CAAA;IAED,OAAO;QACL,MAAM,EAAE,OAAO,CAAC,OAAO;AACvB,QAAA,UAAU,EAAA,UAAA;AACV,QAAA,aAAa,EAAA,aAAA;AACb,QAAA,YAAY,EAAA,YAAA;KACb,CAAA;AACH;;;;"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { Dispatch, SetStateAction } from 'react';
|
|
2
|
-
export declare const useStateWithCallback: <S>(initialState: S, handler?: (
|
|
2
|
+
export declare const useStateWithCallback: <S>(initialState: S, handler?: (prevState: S) => void, runHandler?: boolean) => [S, Dispatch<SetStateAction<S>>];
|
package/dist/esm/index.js
CHANGED
|
@@ -102,6 +102,7 @@ export { CProgress } from './components/progress/CProgress.js';
|
|
|
102
102
|
export { CProgressBar } from './components/progress/CProgressBar.js';
|
|
103
103
|
export { CProgressStacked } from './components/progress/CProgressStacked.js';
|
|
104
104
|
export { CPopover } from './components/popover/CPopover.js';
|
|
105
|
+
export { CRating } from './components/rating/CRating.js';
|
|
105
106
|
export { CSmartTable } from './components/smart-table/CSmartTable.js';
|
|
106
107
|
export { CSmartPagination } from './components/smart-pagination/CSmartPagination.js';
|
|
107
108
|
export { CSidebar } from './components/sidebar/CSidebar.js';
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -14,39 +14,57 @@ import { __module as classnames } from '../../_virtual/index.js';
|
|
|
14
14
|
|
|
15
15
|
var hasOwn = {}.hasOwnProperty;
|
|
16
16
|
|
|
17
|
-
function classNames() {
|
|
18
|
-
var classes =
|
|
17
|
+
function classNames () {
|
|
18
|
+
var classes = '';
|
|
19
19
|
|
|
20
20
|
for (var i = 0; i < arguments.length; i++) {
|
|
21
21
|
var arg = arguments[i];
|
|
22
|
-
if (
|
|
23
|
-
|
|
24
|
-
var argType = typeof arg;
|
|
25
|
-
|
|
26
|
-
if (argType === 'string' || argType === 'number') {
|
|
27
|
-
classes.push(arg);
|
|
28
|
-
} else if (Array.isArray(arg)) {
|
|
29
|
-
if (arg.length) {
|
|
30
|
-
var inner = classNames.apply(null, arg);
|
|
31
|
-
if (inner) {
|
|
32
|
-
classes.push(inner);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
} else if (argType === 'object') {
|
|
36
|
-
if (arg.toString !== Object.prototype.toString && !arg.toString.toString().includes('[native code]')) {
|
|
37
|
-
classes.push(arg.toString());
|
|
38
|
-
continue;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
for (var key in arg) {
|
|
42
|
-
if (hasOwn.call(arg, key) && arg[key]) {
|
|
43
|
-
classes.push(key);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
22
|
+
if (arg) {
|
|
23
|
+
classes = appendClass(classes, parseValue(arg));
|
|
46
24
|
}
|
|
47
25
|
}
|
|
48
26
|
|
|
49
|
-
return classes
|
|
27
|
+
return classes;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function parseValue (arg) {
|
|
31
|
+
if (typeof arg === 'string' || typeof arg === 'number') {
|
|
32
|
+
return arg;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (typeof arg !== 'object') {
|
|
36
|
+
return '';
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (Array.isArray(arg)) {
|
|
40
|
+
return classNames.apply(null, arg);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (arg.toString !== Object.prototype.toString && !arg.toString.toString().includes('[native code]')) {
|
|
44
|
+
return arg.toString();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
var classes = '';
|
|
48
|
+
|
|
49
|
+
for (var key in arg) {
|
|
50
|
+
if (hasOwn.call(arg, key) && arg[key]) {
|
|
51
|
+
classes = appendClass(classes, key);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return classes;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function appendClass (value, newClass) {
|
|
59
|
+
if (!newClass) {
|
|
60
|
+
return value;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (value) {
|
|
64
|
+
return value + ' ' + newClass;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return value + newClass;
|
|
50
68
|
}
|
|
51
69
|
|
|
52
70
|
if (module.exports) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../../../classnames/index.js"],"sourcesContent":["/*!\n\tCopyright (c) 2018 Jed Watson.\n\tLicensed under the MIT License (MIT), see\n\thttp://jedwatson.github.io/classnames\n*/\n/* global define */\n\n(function () {\n\t'use strict';\n\n\tvar hasOwn = {}.hasOwnProperty;\n\
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../../classnames/index.js"],"sourcesContent":["/*!\n\tCopyright (c) 2018 Jed Watson.\n\tLicensed under the MIT License (MIT), see\n\thttp://jedwatson.github.io/classnames\n*/\n/* global define */\n\n(function () {\n\t'use strict';\n\n\tvar hasOwn = {}.hasOwnProperty;\n\n\tfunction classNames () {\n\t\tvar classes = '';\n\n\t\tfor (var i = 0; i < arguments.length; i++) {\n\t\t\tvar arg = arguments[i];\n\t\t\tif (arg) {\n\t\t\t\tclasses = appendClass(classes, parseValue(arg));\n\t\t\t}\n\t\t}\n\n\t\treturn classes;\n\t}\n\n\tfunction parseValue (arg) {\n\t\tif (typeof arg === 'string' || typeof arg === 'number') {\n\t\t\treturn arg;\n\t\t}\n\n\t\tif (typeof arg !== 'object') {\n\t\t\treturn '';\n\t\t}\n\n\t\tif (Array.isArray(arg)) {\n\t\t\treturn classNames.apply(null, arg);\n\t\t}\n\n\t\tif (arg.toString !== Object.prototype.toString && !arg.toString.toString().includes('[native code]')) {\n\t\t\treturn arg.toString();\n\t\t}\n\n\t\tvar classes = '';\n\n\t\tfor (var key in arg) {\n\t\t\tif (hasOwn.call(arg, key) && arg[key]) {\n\t\t\t\tclasses = appendClass(classes, key);\n\t\t\t}\n\t\t}\n\n\t\treturn classes;\n\t}\n\n\tfunction appendClass (value, newClass) {\n\t\tif (!newClass) {\n\t\t\treturn value;\n\t\t}\n\t\n\t\tif (value) {\n\t\t\treturn value + ' ' + newClass;\n\t\t}\n\t\n\t\treturn value + newClass;\n\t}\n\n\tif (typeof module !== 'undefined' && module.exports) {\n\t\tclassNames.default = classNames;\n\t\tmodule.exports = classNames;\n\t} else if (typeof define === 'function' && typeof define.amd === 'object' && define.amd) {\n\t\t// register as 'classnames', consistent with npm package name\n\t\tdefine('classnames', [], function () {\n\t\t\treturn classNames;\n\t\t});\n\t} else {\n\t\twindow.classNames = classNames;\n\t}\n}());\n"],"names":[],"mappings":";;;;;;;;;;AAKA;AACA;AACA,CAAA,CAAC,YAAY;AAEb;AACA,EAAC,IAAI,MAAM,GAAG,EAAE,CAAC,cAAc,CAAC;AAChC;EACC,SAAS,UAAU,IAAI;AACxB,GAAE,IAAI,OAAO,GAAG,EAAE,CAAC;AACnB;AACA,GAAE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;AAC7C,IAAG,IAAI,GAAG,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;IACvB,IAAI,GAAG,EAAE;KACR,OAAO,GAAG,WAAW,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;KAChD;IACD;AACH;GACE,OAAO,OAAO,CAAC;GACf;AACF;AACA,EAAC,SAAS,UAAU,EAAE,GAAG,EAAE;GACzB,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE;IACvD,OAAO,GAAG,CAAC;IACX;AACH;AACA,GAAE,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE;IAC5B,OAAO,EAAE,CAAC;IACV;AACH;AACA,GAAE,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;IACvB,OAAO,UAAU,CAAC,KAAK,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACnC;AACH;GACE,IAAI,GAAG,CAAC,QAAQ,KAAK,MAAM,CAAC,SAAS,CAAC,QAAQ,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE;AACxG,IAAG,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;IACtB;AACH;AACA,GAAE,IAAI,OAAO,GAAG,EAAE,CAAC;AACnB;AACA,GAAE,KAAK,IAAI,GAAG,IAAI,GAAG,EAAE;AACvB,IAAG,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,EAAE;KACtC,OAAO,GAAG,WAAW,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;KACpC;IACD;AACH;GACE,OAAO,OAAO,CAAC;GACf;AACF;AACA,EAAC,SAAS,WAAW,EAAE,KAAK,EAAE,QAAQ,EAAE;GACtC,IAAI,CAAC,QAAQ,EAAE;IACd,OAAO,KAAK,CAAC;IACb;AACH;GACE,IAAI,KAAK,EAAE;AACb,IAAG,OAAO,KAAK,GAAG,GAAG,GAAG,QAAQ,CAAC;IAC9B;AACH;AACA,GAAE,OAAO,KAAK,GAAG,QAAQ,CAAC;GACxB;AACF;EACC,IAAqC,MAAM,CAAC,OAAO,EAAE;AACtD,GAAE,UAAU,CAAC,OAAO,GAAG,UAAU,CAAC;GAChC,MAAA,CAAA,OAAA,GAAiB,UAAU,CAAC;AAC9B,GAAE,MAKM;AACR,GAAE,MAAM,CAAC,UAAU,GAAG,UAAU,CAAC;GAC/B;AACF,EAAC,EAAE,EAAA;;;;;;;;","x_google_ignoreList":[0]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coreui/react-pro",
|
|
3
|
-
"version": "5.0.0",
|
|
3
|
+
"version": "5.1.0-alpha.0",
|
|
4
4
|
"description": "UI Components Library for React.js",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"test:update": "jest --coverage --updateSnapshot"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@coreui/coreui-pro": "^5.0.0",
|
|
44
|
+
"@coreui/coreui-pro": "^5.1.0-alpha.0",
|
|
45
45
|
"@popperjs/core": "^2.11.8",
|
|
46
46
|
"prop-types": "^15.8.1"
|
|
47
47
|
},
|
package/src/components/index.ts
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import React, { forwardRef, HTMLAttributes, ReactNode, useRef, useEffect, useState } from 'react'
|
|
2
2
|
import classNames from 'classnames'
|
|
3
3
|
import PropTypes from 'prop-types'
|
|
4
|
-
import { Transition } from 'react-transition-group'
|
|
5
4
|
|
|
6
5
|
import { CConditionalPortal } from '../conditional-portal'
|
|
7
6
|
import { useForkedRef, usePopper } from '../../hooks'
|
|
8
7
|
import { fallbackPlacementsPropType, triggerPropType } from '../../props'
|
|
9
8
|
import type { Placements, Triggers } from '../../types'
|
|
10
|
-
import {
|
|
9
|
+
import { executeAfterTransition, getRTLPlacement } from '../../utils'
|
|
11
10
|
|
|
12
11
|
export interface CPopoverProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title' | 'content'> {
|
|
13
12
|
/**
|
|
@@ -101,6 +100,7 @@ export const CPopover = forwardRef<HTMLDivElement, CPopoverProps>(
|
|
|
101
100
|
const uID = useRef(`popover${Math.floor(Math.random() * 1_000_000)}`)
|
|
102
101
|
|
|
103
102
|
const { initPopper, destroyPopper } = usePopper()
|
|
103
|
+
const [mounted, setMounted] = useState(false)
|
|
104
104
|
const [_visible, setVisible] = useState(visible)
|
|
105
105
|
|
|
106
106
|
const _delay = typeof delay === 'number' ? { show: delay, hide: delay } : delay
|
|
@@ -133,14 +133,39 @@ export const CPopover = forwardRef<HTMLDivElement, CPopoverProps>(
|
|
|
133
133
|
setVisible(visible)
|
|
134
134
|
}, [visible])
|
|
135
135
|
|
|
136
|
-
|
|
137
|
-
if (
|
|
138
|
-
|
|
139
|
-
|
|
136
|
+
useEffect(() => {
|
|
137
|
+
if (_visible) {
|
|
138
|
+
setMounted(true)
|
|
139
|
+
|
|
140
|
+
if (popoverRef.current) {
|
|
141
|
+
popoverRef.current.classList.remove('fade', 'show')
|
|
142
|
+
destroyPopper()
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
setTimeout(() => {
|
|
146
|
+
if (togglerRef.current && popoverRef.current) {
|
|
147
|
+
if (animation) {
|
|
148
|
+
popoverRef.current.classList.add('fade')
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
initPopper(togglerRef.current, popoverRef.current, popperConfig)
|
|
152
|
+
popoverRef.current.classList.add('show')
|
|
153
|
+
onShow && onShow()
|
|
154
|
+
}
|
|
155
|
+
}, _delay.show)
|
|
140
156
|
}
|
|
141
157
|
|
|
142
|
-
|
|
143
|
-
|
|
158
|
+
return () => {
|
|
159
|
+
if (popoverRef.current) {
|
|
160
|
+
popoverRef.current.classList.remove('show')
|
|
161
|
+
onHide && onHide()
|
|
162
|
+
executeAfterTransition(() => {
|
|
163
|
+
destroyPopper()
|
|
164
|
+
setMounted(false)
|
|
165
|
+
}, popoverRef.current)
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}, [_visible])
|
|
144
169
|
|
|
145
170
|
return (
|
|
146
171
|
<>
|
|
@@ -150,71 +175,31 @@ export const CPopover = forwardRef<HTMLDivElement, CPopoverProps>(
|
|
|
150
175
|
}),
|
|
151
176
|
ref: togglerRef,
|
|
152
177
|
...((trigger === 'click' || trigger.includes('click')) && {
|
|
153
|
-
onClick: () =>
|
|
178
|
+
onClick: () => setVisible(!_visible),
|
|
154
179
|
}),
|
|
155
180
|
...((trigger === 'focus' || trigger.includes('focus')) && {
|
|
156
|
-
onFocus: () =>
|
|
157
|
-
onBlur: () =>
|
|
181
|
+
onFocus: () => setVisible(true),
|
|
182
|
+
onBlur: () => setVisible(false),
|
|
158
183
|
}),
|
|
159
184
|
...((trigger === 'hover' || trigger.includes('hover')) && {
|
|
160
|
-
onMouseEnter: () =>
|
|
161
|
-
onMouseLeave: () =>
|
|
185
|
+
onMouseEnter: () => setVisible(true),
|
|
186
|
+
onMouseLeave: () => setVisible(false),
|
|
162
187
|
}),
|
|
163
188
|
})}
|
|
164
189
|
<CConditionalPortal container={container} portal={true}>
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
popoverRef.current.style.display = 'initial'
|
|
179
|
-
}
|
|
180
|
-
}}
|
|
181
|
-
onExit={onHide}
|
|
182
|
-
onExited={() => {
|
|
183
|
-
destroyPopper()
|
|
184
|
-
}}
|
|
185
|
-
timeout={{
|
|
186
|
-
enter: 0,
|
|
187
|
-
exit: popoverRef.current
|
|
188
|
-
? getTransitionDurationFromElement(popoverRef.current) + 50
|
|
189
|
-
: 200,
|
|
190
|
-
}}
|
|
191
|
-
unmountOnExit
|
|
192
|
-
>
|
|
193
|
-
{(state) => (
|
|
194
|
-
<div
|
|
195
|
-
className={classNames(
|
|
196
|
-
'popover',
|
|
197
|
-
'bs-popover-auto',
|
|
198
|
-
{
|
|
199
|
-
fade: animation,
|
|
200
|
-
show: state === 'entered',
|
|
201
|
-
},
|
|
202
|
-
className,
|
|
203
|
-
)}
|
|
204
|
-
id={uID.current}
|
|
205
|
-
ref={forkedRef}
|
|
206
|
-
role="tooltip"
|
|
207
|
-
style={{
|
|
208
|
-
display: 'none',
|
|
209
|
-
}}
|
|
210
|
-
{...rest}
|
|
211
|
-
>
|
|
212
|
-
<div className="popover-arrow"></div>
|
|
213
|
-
<div className="popover-header">{title}</div>
|
|
214
|
-
<div className="popover-body">{content}</div>
|
|
215
|
-
</div>
|
|
216
|
-
)}
|
|
217
|
-
</Transition>
|
|
190
|
+
{mounted && (
|
|
191
|
+
<div
|
|
192
|
+
className={classNames('popover', 'bs-popover-auto', className)}
|
|
193
|
+
id={uID.current}
|
|
194
|
+
ref={forkedRef}
|
|
195
|
+
role="tooltip"
|
|
196
|
+
{...rest}
|
|
197
|
+
>
|
|
198
|
+
<div className="popover-arrow"></div>
|
|
199
|
+
<div className="popover-header">{title}</div>
|
|
200
|
+
<div className="popover-body">{content}</div>
|
|
201
|
+
</div>
|
|
202
|
+
)}
|
|
218
203
|
</CConditionalPortal>
|
|
219
204
|
</>
|
|
220
205
|
)
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
import React, { forwardRef, Fragment, HTMLAttributes, ReactNode, useId, useState } from 'react'
|
|
2
|
+
import PropTypes from 'prop-types'
|
|
3
|
+
import classNames from 'classnames'
|
|
4
|
+
import { CTooltip } from '../tooltip'
|
|
5
|
+
|
|
6
|
+
type Icon = {
|
|
7
|
+
[key: number]: JSX.Element
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface CRatingProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onChange'> {
|
|
11
|
+
/**
|
|
12
|
+
* The default icon to display when the item is selected.
|
|
13
|
+
*/
|
|
14
|
+
activeIcon?: string | JSX.Element | Icon
|
|
15
|
+
/**
|
|
16
|
+
* Enables the clearing upon clicking the selected item again.
|
|
17
|
+
*/
|
|
18
|
+
allowClear?: boolean
|
|
19
|
+
/**
|
|
20
|
+
* A string of all className you want applied to the component.
|
|
21
|
+
*/
|
|
22
|
+
className?: string
|
|
23
|
+
/**
|
|
24
|
+
* Toggle the disabled state for the component.
|
|
25
|
+
*/
|
|
26
|
+
disabled?: boolean
|
|
27
|
+
/**
|
|
28
|
+
* If enabled, only the currently selected icon will be visibly highlighted.
|
|
29
|
+
*/
|
|
30
|
+
highlightOnlySelected?: boolean
|
|
31
|
+
/**
|
|
32
|
+
* The default icon to display when the item is not selected.
|
|
33
|
+
*/
|
|
34
|
+
icon?: string | JSX.Element | Icon
|
|
35
|
+
/**
|
|
36
|
+
* The maximum value the user can select.
|
|
37
|
+
*/
|
|
38
|
+
max?: number
|
|
39
|
+
/**
|
|
40
|
+
* The name attribute of the radio input elements.
|
|
41
|
+
*/
|
|
42
|
+
name?: string
|
|
43
|
+
/**
|
|
44
|
+
* Execute a function when a user changes the selected element.
|
|
45
|
+
*/
|
|
46
|
+
onChange?: (value: number | null) => void
|
|
47
|
+
/**
|
|
48
|
+
* Execute a function when a user hover the element.
|
|
49
|
+
*/
|
|
50
|
+
onHover?: (value: number) => void
|
|
51
|
+
/**
|
|
52
|
+
* Minimum increment value change allowed.
|
|
53
|
+
*/
|
|
54
|
+
precision?: number
|
|
55
|
+
/**
|
|
56
|
+
* Toggle the readonly state for the component.
|
|
57
|
+
*/
|
|
58
|
+
readOnly?: boolean
|
|
59
|
+
/**
|
|
60
|
+
* Size the component small, large, or custom if you define custom icons with custom height.
|
|
61
|
+
*/
|
|
62
|
+
size?: 'sm' | 'lg' | 'custom'
|
|
63
|
+
/**
|
|
64
|
+
* Enable tooltips with default values or set specific labels for each icon.
|
|
65
|
+
*/
|
|
66
|
+
tooltips?: boolean | string[]
|
|
67
|
+
/**
|
|
68
|
+
* The `value` attribute of component.
|
|
69
|
+
*
|
|
70
|
+
* @controllable onChange
|
|
71
|
+
* */
|
|
72
|
+
value?: number
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const CConditionalTooltip = ({
|
|
76
|
+
children,
|
|
77
|
+
content,
|
|
78
|
+
tooltip,
|
|
79
|
+
}: {
|
|
80
|
+
children: ReactNode
|
|
81
|
+
content?: ReactNode
|
|
82
|
+
tooltip?: boolean
|
|
83
|
+
}) => {
|
|
84
|
+
return tooltip ? (
|
|
85
|
+
<CTooltip content={content}>
|
|
86
|
+
<span>{children}</span>
|
|
87
|
+
</CTooltip>
|
|
88
|
+
) : (
|
|
89
|
+
children
|
|
90
|
+
)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export const CRating = forwardRef<HTMLDivElement, CRatingProps>(
|
|
94
|
+
(
|
|
95
|
+
{
|
|
96
|
+
activeIcon,
|
|
97
|
+
allowClear,
|
|
98
|
+
className,
|
|
99
|
+
disabled,
|
|
100
|
+
highlightOnlySelected,
|
|
101
|
+
icon,
|
|
102
|
+
max = 5,
|
|
103
|
+
name,
|
|
104
|
+
onChange,
|
|
105
|
+
onHover,
|
|
106
|
+
precision = 1,
|
|
107
|
+
readOnly,
|
|
108
|
+
size,
|
|
109
|
+
tooltips,
|
|
110
|
+
value,
|
|
111
|
+
...rest
|
|
112
|
+
},
|
|
113
|
+
ref,
|
|
114
|
+
) => {
|
|
115
|
+
const [cleared, setCleared] = useState(false)
|
|
116
|
+
const [currentValue, setCurrentValue] = useState(value ?? null)
|
|
117
|
+
const [hoverValue, setHoverValue] = useState<number | null>(null)
|
|
118
|
+
const [tooltipValue, setTooltipValue] = useState<number | string | null>(null)
|
|
119
|
+
const _name = name || useId()
|
|
120
|
+
|
|
121
|
+
const handleMouseEnter = (value: number) => {
|
|
122
|
+
if (disabled || readOnly) {
|
|
123
|
+
return
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
onHover && onHover(value)
|
|
127
|
+
setHoverValue(value)
|
|
128
|
+
value && setTooltipValue(value)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const handleOnChange = (value: number) => {
|
|
132
|
+
if (disabled || readOnly) {
|
|
133
|
+
return
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (cleared) {
|
|
137
|
+
setCleared(false)
|
|
138
|
+
return
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
setCurrentValue(value)
|
|
142
|
+
onChange && onChange(value)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const handleOnClick = (value: number) => {
|
|
146
|
+
if (disabled || readOnly) {
|
|
147
|
+
return
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (allowClear && value === currentValue) {
|
|
151
|
+
setCleared(true)
|
|
152
|
+
onChange && onChange(null)
|
|
153
|
+
setCurrentValue(null)
|
|
154
|
+
setHoverValue(null)
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return (
|
|
159
|
+
<div
|
|
160
|
+
className={classNames(
|
|
161
|
+
'rating',
|
|
162
|
+
{
|
|
163
|
+
[`rating-${size}`]: size,
|
|
164
|
+
disabled: disabled,
|
|
165
|
+
readonly: readOnly,
|
|
166
|
+
},
|
|
167
|
+
className,
|
|
168
|
+
)}
|
|
169
|
+
onMouseLeave={() => !disabled && !readOnly && setHoverValue(null)}
|
|
170
|
+
role="radiogroup"
|
|
171
|
+
{...rest}
|
|
172
|
+
ref={ref}
|
|
173
|
+
>
|
|
174
|
+
{Array.from({ length: max }, (_, index) => {
|
|
175
|
+
const numberOfRadios = 1 / precision
|
|
176
|
+
|
|
177
|
+
return (
|
|
178
|
+
<CConditionalTooltip
|
|
179
|
+
key={index}
|
|
180
|
+
{...(tooltips && {
|
|
181
|
+
content: Array.isArray(tooltips)
|
|
182
|
+
? tooltips[index]
|
|
183
|
+
: precision
|
|
184
|
+
? tooltipValue
|
|
185
|
+
: index + 1,
|
|
186
|
+
tooltip: true,
|
|
187
|
+
})}
|
|
188
|
+
>
|
|
189
|
+
<div className="rating-item">
|
|
190
|
+
{Array.from({ length: numberOfRadios }, (_, _index) => {
|
|
191
|
+
const isNotLastItem = _index + 1 < numberOfRadios
|
|
192
|
+
const value =
|
|
193
|
+
numberOfRadios === 1 ? index + 1 : index + (_index + 1) * (1 * precision)
|
|
194
|
+
const id = useId()
|
|
195
|
+
|
|
196
|
+
const isItemChecked = () => value === currentValue
|
|
197
|
+
|
|
198
|
+
const isItemActive = () => {
|
|
199
|
+
if (
|
|
200
|
+
highlightOnlySelected
|
|
201
|
+
? hoverValue === value
|
|
202
|
+
: hoverValue && hoverValue >= value
|
|
203
|
+
) {
|
|
204
|
+
return true
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
if (
|
|
208
|
+
hoverValue === null &&
|
|
209
|
+
(highlightOnlySelected
|
|
210
|
+
? isItemChecked()
|
|
211
|
+
: currentValue && currentValue >= value)
|
|
212
|
+
) {
|
|
213
|
+
return true
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return false
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return (
|
|
220
|
+
<Fragment key={value}>
|
|
221
|
+
<label
|
|
222
|
+
className={classNames('rating-item-label', {
|
|
223
|
+
active: isItemActive(),
|
|
224
|
+
})}
|
|
225
|
+
htmlFor={id}
|
|
226
|
+
onClick={() => handleOnClick(value)}
|
|
227
|
+
onMouseEnter={() => handleMouseEnter(value)}
|
|
228
|
+
{...(isNotLastItem && {
|
|
229
|
+
style: {
|
|
230
|
+
zIndex: 1 / precision - _index,
|
|
231
|
+
position: 'absolute',
|
|
232
|
+
width: `${precision * (_index + 1) * 100}%`,
|
|
233
|
+
overflow: 'hidden',
|
|
234
|
+
opacity: 0,
|
|
235
|
+
},
|
|
236
|
+
})}
|
|
237
|
+
>
|
|
238
|
+
{icon ? (
|
|
239
|
+
<div className="rating-item-custom-icon">
|
|
240
|
+
{(icon as Icon)[value] ?? icon}
|
|
241
|
+
</div>
|
|
242
|
+
) : (
|
|
243
|
+
<div className="rating-item-icon"></div>
|
|
244
|
+
)}
|
|
245
|
+
{activeIcon && (
|
|
246
|
+
<div className="rating-item-custom-icon-active">
|
|
247
|
+
{(activeIcon as Icon)[value] ?? activeIcon}
|
|
248
|
+
</div>
|
|
249
|
+
)}
|
|
250
|
+
</label>
|
|
251
|
+
<input
|
|
252
|
+
className="rating-item-input"
|
|
253
|
+
checked={isItemChecked()}
|
|
254
|
+
disabled={disabled || readOnly}
|
|
255
|
+
id={id}
|
|
256
|
+
name={_name}
|
|
257
|
+
onChange={() => handleOnChange(value)}
|
|
258
|
+
onFocus={() => handleMouseEnter(value)}
|
|
259
|
+
type="radio"
|
|
260
|
+
value={value}
|
|
261
|
+
/>
|
|
262
|
+
</Fragment>
|
|
263
|
+
)
|
|
264
|
+
})}
|
|
265
|
+
</div>
|
|
266
|
+
</CConditionalTooltip>
|
|
267
|
+
)
|
|
268
|
+
})}
|
|
269
|
+
</div>
|
|
270
|
+
)
|
|
271
|
+
},
|
|
272
|
+
)
|
|
273
|
+
|
|
274
|
+
CRating.propTypes = {
|
|
275
|
+
children: PropTypes.node,
|
|
276
|
+
activeIcon: PropTypes.any,
|
|
277
|
+
allowClear: PropTypes.bool,
|
|
278
|
+
disabled: PropTypes.bool,
|
|
279
|
+
highlightOnlySelected: PropTypes.bool,
|
|
280
|
+
icon: PropTypes.any,
|
|
281
|
+
max: PropTypes.number,
|
|
282
|
+
name: PropTypes.string,
|
|
283
|
+
onChange: PropTypes.func,
|
|
284
|
+
onHover: PropTypes.func,
|
|
285
|
+
precision: PropTypes.number,
|
|
286
|
+
readOnly: PropTypes.bool,
|
|
287
|
+
size: PropTypes.oneOf(['sm', 'lg', 'custom']),
|
|
288
|
+
value: PropTypes.number,
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
CRating.displayName = 'CRating'
|