Add a class to react-day-picker? - react-day-picker

How can I add a class to react-day-picker's today button?
It seems to be possible from the documentation:
http://react-day-picker.js.org/api/DayPicker#classNames
const dayPickerClassNames = { todayButton: 'newClass' };
<DayPicker
classNames={dayPickerClassNames}
/>
However Im getting an error:
Warning: Failed prop type: The prop `classNames.day` is marked as required in `DayPicker`, but its value is `undefined`.

According to the API, it expects the following keys (ie, it needs the container, wrapper, .. months.. month.. day.. etc. keys), but you are only providing the todayButton key/value, apparently you need to provide each key/value pair.
You should be able to import the default classNames object, and then just update the todayButton value like so:
import classNames from '../classNames' // this path is probably not correct
const dayPickerClassNames = { ...classNames, todayButton: 'newClass' };
<DayPicker
classNames={dayPickerClassNames}
/>

const defaultClassNames = DayPicker.defaultProps.classNames,
newClassNames = { ...datePickerClassNames,
container: `${defaultClassNames.container} MY_CONTAINER`
};
...
<DayPicker classNames={dayPickerClassNames}/>
I'd recommend appending the default class with your own as in the example above the default container class appended with MY_CONTAINER class.

I believe it may just be parsing the word day and looking for a className for that parsed day******* I think I would just try defining the key:value relationship as they have in their documentation.
// const dayPickerClassNames = { todayButton: 'newClass' };
<DayPicker
classNames={ todayButton: 'newClass' }
/>

Related

Default value is not passed to prop

The code below should display my prop default value ("test") since it received no other value. Yet it displays nothing. Why not?
<template>
<div>
{{ propValue }}
</div>
</template>
<script setup lang="ts">
import { defineProps } from "vue"
const props = defineProps<{
myProp: {
type: string
default: "test"
}
}>()
const propValue = props.myProp
</script>
There are two reasons why.
When you use props with TypeScript you lose the ability to set default values, but it can be fixed using the withDefaults macro (you also need to separately declare a Props interface). Side note: I would not use the alternative experimental "Reactivity Transform" solution noted in the docs (it's being removed soon)
export interface Props {
myProp?: string;
}
const props = withDefaults(defineProps<Props>(), {
myProp: 'test'
});
This one isn't actually strictly necessary, but props is a reactive object, and when you assign a single property of props to a new variable, the reactivity breaks. In order to maintain reactivity and stay synced with any future changes to props, use the toRef function
const propValue = toRef(props, 'myProp');
and be sure to import it: import { defineProps, toRef } from 'vue';

Vue - using props on custom elements fails using createApp and mount?

We would like to pass props to custom elements that uses createApp
// index.html
<div id="my-root">
<my-element prop1="abc"></my-element>
</div>
// my-element.vue
<script lang="ts" setup>
const props = defineProps<{ prop1: number }>();
</script>
<template>
{{props.prop1}}
</template>
This works fine, but as our custome element get bigger we would like to register components and use e.g pinia and other tools. Do use those we need to add createApp and mount it. But then prop1 is always undefined
// main.ts
import ...<lots of imports>
import AppCe from "./AppWebComponent.ce.vue";
import { createPinia } from "pinia";
// Adding code below is causing prop1 to be undefined - if we skip this part, prop1 works fine
const pinia = createPinia();
const app = createApp(App);
app.use(pinia).use(ConfirmDialog);
app.component(...<lots of components>);
app.mount("#my-root");
const ceApp = defineCustomElement(AppCe);
customElements.define("my-element", ceApp);
update:
Here's a sample without: https://stackblitz.com/edit/vue3-script-setup-with-vite-56rizn?file=src/my-element/my-element-main.js
And here's a sample with the createApp: https://stackblitz.com/edit/vue3-script-setup-with-vite-gtkbaq?file=index.html
Any idea on how we could solve this?
We have a fallback, that is to do a getElementById and read the attribute value in the mounted callback - but that is not an optimal solution.
Thanks for any ideas!
update2:
Here's an attempt using #duannex suggestion. We're getting closer, the app is availible, components registered, but still no sigar. : https://stackblitz.com/edit/vue3-script-setup-with-vite-ofwcjt?file=src/my-element/defineCustomElementWrapped.js
Based on update2 with the wrapped defineCustomElement; Just pass the props to the render function:
render() {
return h(component, this.$props)
},
https://stackblitz.com/edit/vue3-script-setup-with-vite-vfdnvg?file=src/my-element/defineCustomElementWrapped.js

Font Awesome 6 (beta) and dynamic icon name in Next JS

I am developing a website with Next JS. This is the first time I use this language and I still have a lot to learn.
Now, I have a Pro subscription to Font Awesome and I am looking to use their component directly in my project, as described in their guides.
https://fontawesome.com/v6.0/docs/web/use-with/react/
https://fontawesome.com/v6.0/docs/web/use-with/react/add-icons
Basically, just using a component like this:
<FontAwesomeIcon icon={brands("google")} />
It works.
The problem, which I can't solve, is how to set the "google" value dynamically, in a previously initialized variable. I need that because this values are coming dynamically from a database.
If I try:
var example = "google";
<FontAwesomeIcon icon={brands(example)} />
Then I receive this error: "Only string literals are supported when referencing icons (use a string here instead)".
Anyone have any ideas?
The way you import your icons uses a babel macro. It means that the referenced icon must be known at build time. It just won't work, because Babel can't figure out what icon should be imported, it can only be done during runtime. That's why it tells you that only string literals are supported.
So you need to use the second method, explained in the docs. You have to have some kind of mapping between icon and the value from DB and then grab the relevant icon. Something like this:
// not sure about exact import
import { faGoogle } from '#fortawesome/free-brand-svg-icons';
// you'd put all valid values that can come from the backend here
const myIcons = {
google: faGoogle
}
// ...
const example = 'google';
<FontAwesomeIcon icon={myIcons[example]} />
The other option is to use library.add, explained here and then do the same as above but instead of imported icon use a string, e.g. google: 'fa-brands fa-google' (again, not sure about exact value here).
Would the following work?
var example = ['fab', 'google'];
<FontAwesomeIcon icon={example} />
P.S. It is recommended to use the let or const keywords with ES6.
// Utils
const UpperFirst = (sentence) => {
if (!sentence || (typeof sentence !== 'string')) return null
return `${sentence.charAt(0).toUpperCase()}${sentence.slice(1)}`
}
// React Generic Component
import React from 'react'
import { FontAwesomeIcon } from '#fortawesome/react-fontawesome'
import * as solid from '#fortawesome/free-solid-svg-icons'
import * as regular from '#fortawesome/free-regular-svg-icons'
import { UpperFirst } from '#utils'
const GenFontAwe = ({ isReg, customClass, nameIco }) => {
if (!nameIco) return null
const finalName = nameIco.split('-').map((cv, ind) => ind === 0 ? cv : UpperFirst(cv)).join('')
const finalIcon = isReg ? regular[finalName] : solid[finalName]
if(!finalIcon) return null
return <FontAwesomeIcon icon={finalIcon} className={customClass || ''} />
}
export default GenFontAwe
// Consume that way:
<GenFontAwe nameIco='fa-folder-open' isReg customClass="h1 p-5" />

Change css variables dynamically in angular

In my angular project, I have some css variables defined in top level styles.scss file like this. I use these variable at many places to keep the whole theme consistent.
:root {
--theme-color-1: #f7f7f7;
--theme-color-2: #ec4d3b;
--theme-color-3: #ffc107;
--theme-color-4: #686250;
--font-weight: 300
}
How can I update values of these variables dynamically from app.component.ts ? And What is the clean way to do this in angular ?
You can update them using
document.documentElement.style.setProperty('--theme-color-1', '#fff');
If u want to update many values, then create a object
this.styles = [
{ name: 'primary-dark-5', value: "#111" },
{ name: 'primary-dark-7_5', value: "#fff" },
];
this.styles.forEach(data => {
document.documentElement.style.setProperty(`--${data.name}`, data.value);
});
The main thing here is document.documentElement.style.setProperty. This line allows you to access the root element (HTML tag) and assigns/overrides the style values.
Note that the names of the variables should match at both places(css and js files)
if you don't want to use document API, then you can use inline styles on HTML tag directly
const styleObject = {};
this.styles.forEach(data => {
styleObject[`--${data.name}`] = data.value;
});
Then In your template file using ngStyle (https://angular.io/api/common/NgStyle)
Set a collection of style values using an expression that returns
key-value pairs.
<some-element [ngStyle]="objExp">...</some-element>
<html [ngStyle]="styleObject" >...</html> //not sure about quotes syntax
Above methods do the same thing, "Update root element values" but in a different way.
When you used :root, the styles automatically got attached to HTML tag
Starting with Angular v9 you can use the style binding to change a value of a custom property
<app-component-name [style.--theme-color-1="'#CCC'"></app-component-name>
Some examples add variables directly to html tag and it seem in the element source as a long list. I hope this helps to you,
class AppComponent {
private variables=['--my-var: 123;', '--my-second-var: 345;'];
private addAsLink(): void {
const cssVariables = `:root{ ${this.variables.join('')}};
const blob = new Blob([cssVariables]);
const url = URL.createObjectURL(blob);
const cssElement = document.createElement('link');
cssElement.setAttribute('rel', 'stylesheet');
cssElement.setAttribute('type', 'text/css');
cssElement.setAttribute('href', url);
document.head.appendChild(cssElement);
}
}

Meteor Flow Router React: I am passing a component as a prop, and I want to include a prop in that component

See this code:
authenticatedRoutes.route( '/study/:studyId/study_settings', {
name: 'study_settings',
action(params, queryParams) {
console.log(queryParams);
Session.set('studyId', params.studyId);
mount( Default, { yield: <PageContainer pageName='Study Settings' page={<StudySettings />}/> } );
}
});
As you can see the page prop? in the mount function? I am passing <StudySettings /> component
well I want to pass a prop into this component
but when I try <StudySettings queryPage=queryParams.subPage /> I get compile error.
How can I do this?
When you want to pass a prop to a ReactJS Component that is a variable you need to use {} so in your case you need to do something like this
<StudySettings queryPage={ queryParams.subPage } />
Let me know if you have anyother questions!

Resources